В чем смысл знака числа (#) в регулярном выражении Perl?

В чем смысл выражения ниже в perl?

($script = $0) =~ s#^.*/##g;

Я пытаюсь понять оператор = ~ вместе с утверждением в правой части s # ^. */## g.

Спасибо

Ответ 1

=~ применяет вещь справа (совпадение с образцом или поиск и замена) на предмет слева. Там есть много документации о =~, поэтому я просто собираюсь указать вам довольно хороший.

Там есть пара идиом, которые не очевидны и не задокументированы, что может сбить вас с толку. Пусть они будут покрыты.

Сначала это...

($copy = $original) =~ s/foo/bar/;

Это способ копирования переменной и выполнения поиска и замены на нем за один шаг. Это эквивалентно:

$copy = $original;
$copy =~ s/foo/bar/;

=~ работает на том, что находится слева после того, как был запущен код левой руки. ($copy = $original) оценивается как $copy, поэтому =~ действует на копию.

s#^.*/##g - это то же самое, что и s/^.*\///g, но используя альтернативные разделители, чтобы избежать Синтаксический синдром откидывания, Вы можете использовать что угодно как разделитель регулярных выражений. # распространен, хотя я считаю его уродливым и трудным для чтения. Я предпочитаю {}, потому что они балансируют. s{^.*/}{}g является эквивалентным кодом.

Развертывание идиом, у вас есть это:

$script = $0;
$script =~ s{^.*/}{}g;

$0 - это имя script. Таким образом, это код для копирования имени script и разбивки всех до последней косой черты (.* является жадным и будет соответствовать как можно больше). Он получает только имя файла script.

/g указывает на выполнение совпадения в строке столько раз, сколько возможно. Так как это может только когда-либо совпадать один раз (^ привязывает его к началу строки), это нецелесообразно.

Там лучший и безопасный способ сделать это.

use File::Basename;
$script = basename($0);

Ответ 2

Это очень, очень просто:

Котировочные выражения Perl могут принимать множество разных символов в качестве разделителей разделов. Сепаратор сразу после команды (в этом случае s) является разделителем для остальной части операции. Например:

 # Out with the "Old" and "In" with the new

 $string =~ s/old/new/;
 $string =~ s#old#new#;
 $string =~ s(old)(new);
 $string =~ [email protected]@[email protected];

Все четыре из этих выражений - одно и то же. Они заменяют строку old на new в моей $string. Все, что приходит после s, является разделителем. Обратите внимание, что в скобках, фигурных скобках и квадратных скобках используются корректировки. Это хорошо работает для q и qq, которые можно использовать вместо одиночных кавычек и двойных кавычек:

print "The value of \$foo is \"foo\"\n";   # A bit hard to read
print qq/The value of \$foo is "$foo"\n/;  # Maybe slashes weren't a great choice...
print qq(The value of \$foo is "$foo"\n);  # Very nice and clean!
print qq(The value of \$foo is (believe it or not) "$foo"\n); #Still works!

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

В большинстве случаев настоятельно рекомендуется придерживаться формы s/.../.../ только для удобства чтения. Это то, к чему люди привыкли, и легко усваивается. Однако, что, если у вас есть это?

$bin_dir =~ s/\/home\/([^\/]+)\/bin/\/Users\/$1\bin/;

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

$bin_dir =~ s#/home/([^/]+)/bin#/Users/$1/bin#;

Это немного сложно прочитать, но, по крайней мере, мне не нужно процитировать каждую косую черту и обратную косую черту, поэтому мне легче увидеть, что я заменяю. Регулярные выражения сложны, потому что хороших персонажей цитат трудно найти. Различные специальные символы, такие как ^, *, | и + являются магическими символами регулярного выражения и, вероятно, могут быть в регулярном выражении, используется #. Это не часто встречается в строках, и в регулярном выражении оно не имеет особого значения, поэтому оно не будет использоваться.


Возвращаясь к исходному вопросу:

($script = $0) =~ s#^.*/##g;

является эквивалентом:

($script = $0) =~ s/^.*\///g;

Но поскольку исходный программист не хотел возвращать эту косую черту, они изменили символ разделителя.

Что касается:

($ script= $0) = ~ s # ^. */## g; `

Это то же самое, что сказать:

$script = $0;
$script =~ s#^.*/##g;

Вы назначаете переменную $script и выполняете замену за один шаг. Это очень распространено в Perl, но сначала это трудно понять.

Кстати, если я понимаю это основное выражение (Удаление всех символов до последней косой черты. Это было бы более чистым:

use File::Basename;
...

$script = basename($0);

Намного легче читать и понимать - даже для старой руки Perl.

Ответ 3

В perl вы можете использовать много видов символов в качестве символов цитирования (строка, регулярное выражение, список). давайте сломаем его:

  • Присвойте переменной $script содержимое $0 (строка, содержащая имя вызывающего script.)
  • Символ =~ - это оператор привязки . Он вызывает регулярное выражение или поиск и замену регулярных выражений. В этом случае он соответствует новой переменной $script.
  • Символ s указывает на поиск и замену регулярного выражения.
  • Символ # используется как разделитель для регулярного выражения. Характер кавычки шаблона регулярного выражения обычно является символом /, но вы можете использовать другие, в том числе # в этом случае.
  • Регулярное выражение ^.*/. Это означает, что "в начале строки поиск нулевого или большего количества символов до косой черты. Это будет удерживать захват в каждой строке, кроме символов новой строки (который . не соответствует по умолчанию.)
  • #, указывающий начало значения "replace". Обычно у вас есть шаблон, который использует любую захваченную часть первой строки.
  • # снова. Это завершает шаблон замены. Поскольку между началом и концом шаблона замены не было ничего, все, что было найдено в первом, заменено ничем.
  • g или глобальное соответствие. Поиск и замена будут продолжаться столько раз, сколько он соответствует значению.

Эффективно ищет и опустошает каждое значение перед значением /, но сохраняет все новые строки в имени script. Это действительно ленивый способ получить имя script при вызове в длинном script, который работает только с unix-подобным путем.

Если у вас есть шанс, подумайте о замене с помощью File::Basename, основного модуля в Perl:

use File::Basename;

# later ... 

my $script = fileparse($0);