Каково различие между использованием 1$ по сравнению с \1 в Perl regex замены?

Я отлаживаю некоторый код и задался вопросом, существует ли какое-либо практическое различие между 1$ и \1 в Perl regex замены

Например:

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

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

print $package_name; # Some::Package

Этот после строки кажется функционально эквивалентным:

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

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

11
задан Sinan Ünür 18 June 2010 в 13:00
поделиться

2 ответа

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

#!/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-последовательности доступны в конструкциях, которые интерполировать и в транслитерации…

\ 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};
14
ответ дан 3 December 2019 в 05:11
поделиться

Из perldoc perlre:

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

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

8
ответ дан 3 December 2019 в 05:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: