В чем разница между использованием $ 1 против \ 1 в подстановках в регулярных выражениях Perl? - PullRequest
11 голосов
/ 18 июня 2010

Я отлаживаю некоторый код и спрашиваю себя, есть ли практическая разница между $ 1 и \ 1 в подстановках регулярного выражения Perl

Например:

my $package_name = "Some::Package::ButNotThis";

$package_name =~ s{^(\w+::\w+)}{$1};  

print $package_name; # Some::Package

Следующая строка выглядит функционально эквивалентной:

$package_name =~ s{^(\w+::w+)}{\1};

Есть ли тонкие различия между этими двумя утверждениями? Они ведут себя по-разному в разных версиях Perl?

Ответы [ 2 ]

14 голосов
/ 18 июня 2010

Во-первых, вы всегда должны использовать предупреждений при разработке:

#!/usr/bin/perl

use strict; use warnings;

my $package_name = "Some::Package::ButNotThis";

$package_name =~ s{^(\w+::\w+)}{\1};

print $package_name, "\n";

Выход:

\1 better written as $1 at C:\Temp\x.pl line 7.

Когда вы получаете предупреждение, которое вы не понимаете, добавьте диагностика :

C:\Temp> perl -Mdiagnostics x.pl
\1 better written as $1 at x.pl line 7 (#1)
    (W syntax) Outside of patterns, backreferences live on as variables.
    The use of backslashes is grandfathered on the right-hand side of a
    substitution, but stylistically it's better to use the variable form
    because other Perl programmers will expect it, and it works better if
    there are more than 9 backreferences.

Почему это работает лучше, если существует более 9 обратных ссылок? Вот пример:

#!/usr/bin/perl

use strict; use warnings;

my $t = (my $s = '0123456789');
my $r = join '', map { "($_)" } split //, $s;

$s =~ s/^$r\z/\10/;
$t =~ s/^$r\z/$10/;

print "[$s]\n";
print "[$t]\n";

Выход:

C:\Temp> x
]
[9]

Если это не проясняет, взгляните на:

C:\Temp> x | xxd
0000000: 5b08 5d0d 0a5b 395d 0d0a                 [.]..[9]..

См. Также perlop :

Следующие escape-последовательности доступны в конструкциях, которые интерполируют и в транслитерации & hellip;

\10 восьмеричное 8 десятичное число. Итак, запасная часть содержала код символа для BACKSPACE.

NB

Между прочим, ваш код не выполняет то, что вы хотите: то есть он будет не печатать Some::Package какой-то пакет вопреки тому, что говорит ваш комментарий, потому что все, что вы делаете, это заменяет Some::Package на Some::Package без прикосновения ::ButNotThis.

Вы можете сделать:

($package_name) = $package_name =~ m{^(\w+::\w+)};

или

$package_name =~ s{^(\w+::\w+)(?:::\w+)*\z}{$1};
8 голосов
/ 18 июня 2010

С perldoc perlre :

Конструкция скобок "(...)" создает буферы захвата. Ссылаясь на текущее содержимое буфера позже, в рамках того же шаблона, используйте \ 1 для первого, \ 2 для второго и т. Д. Вне матча использовать «$» вместо «\».

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

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