В чем разница, если использовать расщепленный шаблон с косой чертой // или кавычками '' | ""? - PullRequest
3 голосов
/ 07 января 2020

Иногда меня укусили действительно базовые c вещи. Я вспомнил поведение split, основанное на использовании PATTERN в качестве строки или регулярного выражения. Теперь, читая документацию , кажется, что такого различия нет, во всех документах есть только один случай (awk -подобное поведение), когда шаблон представлен в виде строки в кавычках, в любом другом примере шаблон находится между косыми чертами. , как регулярное выражение Тем не менее, я нашел примеры / учебные пособия здесь и там , например, где упоминается различие между символами, строками и шаблонами. Тем не менее, в тестах я не обнаружил больше различий, кроме того, что при разбиении на sla sh было бы лучше использовать кавычки (split '/', $some_string).

Моя конкретная проблема c сегодня заключалась в разделении имен файлов на точку . и ожидая разбить на строковый шаблон. К моему удивлению, шаблон '.' все еще считался регулярным выражением, поэтому следующий сценарий не работает с этой целью:

use strict; use warnings; use 5.010;

my ( @x ) = split '.', 'dir/some_file.ext';
say "@x";

Я знаю, как исправить свой сценарий (используя шаблон регулярных выражений), но я все еще не понимаю Не знаете, в чем отличие использования шаблона в качестве строки ('.') и регулярного выражения (/./)?

Ответы [ 3 ]

5 голосов
/ 07 января 2020

Независимо от того, какой синтаксис вы используете, первый операнд split' должен соответствовать шаблону регулярного выражения. [1]

Таким образом, split '.' и split /./ оба разделяются в шаблоне регулярных выражений ., что означает, что возвращаемые строки разделяются любым символом, кроме новой строки.

Обратите внимание, что строковые литералы в одинарных кавычках ('...', q'...', q!...!, q{...}, et c), строковые литералы в двойных кавычках ("...", qq"...", qq!...!, qq{...}, et c) и литералы регулярных выражений (qr/.../, /.../, m/.../, s/...//, et c) имеют разные правила синтаксического анализа. Например, split "\+" и split /\+/ будут иметь разные эффекты, но только потому, что "\+" - это просто странный способ написания "+".

Я рекомендую всегда , используя совпадение оператор (например, /.../) или оператор qr (например, qr/.../) над строковым литералом (за исключением, конечно, ' '). Они лучше всего подходят для построения шаблона регулярных выражений, и они сообщают вашему читателю, что вы создаете шаблон регулярных выражений.


  1. Два исключения:

    • Оператор соответствия обрабатывается как литерал строки-регулярного выражения. Например, /.../ обрабатывается как qr/.../.

    • Выражение, которое оценивается как строка, состоящая из одного пробела (' ' и " ", но не / / или qr/ /) означает, что возвращаемые строки разделяются пробелами, а начальные пробелы следует игнорировать.

4 голосов
/ 07 января 2020

Да, в большинстве случаев split /PATTERN/, $str и split "PATTERN", $str делают одно и то же. В строковой версии строка обычно обрабатывается как регулярное выражение

Страницы, на которые вы ссылаетесь, не упоминают в своих примерах, что если разделитель содержит какие-либо специальные символы регулярного выражения, они должны быть экранированы, даже используя строку синтаксис. Например,

@parts = split '|', $str;  # Oops, gives a list of single chars including |
@parts = split '\|', $str; # Separates on | character

Если разделитель представляет собой переменную, которая может содержать специальные символы регулярного выражения, вам потребуется функция quotemeta, возможно, путем добавления \Q в интерполяцию.

@parts = split quotemeta($sep), $str;
@parts = split "\Q$sep", $str;        # Same thing

Конечно, одинарные кавычки 'TEXT' и двойные кавычки "TEXT" имеют много различий, но это не имеет прямого отношения к функции split.

Фактические различия между split /PATTERN/, $str и split "PATTERN", $str:

  • Существуют различные правила экранирования символов в синтаксисе // и синтаксисе "".
  • С помощью /PATTERN/ можно добавить Флаги модификаторов регулярных выражений. Например, split /\bend$/mi, $str разбивает слово «конец», игнорируя регистр, когда оно появляется в конце строки. (Со строкой вам потребуется синтаксис, такой как "(?mi:\\bend\$)".)
  • Выражение, которое оценивается как строка " ", имеет специальное поведение, игнорируя начальные пробелы и разделяя их на пробелы. Использование / / не использует этот особый случай, а просто разбивает каждый пробел.
0 голосов
/ 07 января 2020

Следующий фрагмент кода разбивает полный путь на его компоненты. Он использует разделитель ! в регулярных выражениях, чтобы избежать экранирования /, так как это регулярное выражение по умолчанию разделитель - это облегчает чтение (понимание) кода

use strict;
use warnings; 
use 5.010;

use Data::Dumper;

my %parts;

my $path = '/home/user/docs/file.ext';

my @components = qw(path name ext);

@parts{@components} = ( $path =~ m!(.*?)/(\w+)\.(\w+)! );

say Dumper(\%parts);

вывод

$VAR1 = {
          'path' => '/home/user/docs',
          'ext' => 'ext',
          'name' => 'file'
        };

Пожалуйста, посетите perlrequick , perlre , perlref и найдите delimiter .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...