Что такое «перевод строки в конце» по отношению к метасимволу $? - PullRequest
2 голосов
/ 07 марта 2020

Я изучаю регулярные выражения из Освоение регулярных выражений, 3-е издание , и я натолкнулся на утверждение, что $ немного сложнее , чем ^, что удивило меня, так как я думал, что они «симметричны», за исключением случаев, когда они означают их буквальные аналоги.

Фактически, на странице 129 их описание немного отличается, с больше слов потрачено на $; однако я все еще смущен этим.

  • Относительно ^, описаны только две ясные альтернативы:

Каретка ^ совпадений в начале искомого текста, и, если в расширенном режиме привязки строки, после любой новой строки. [...] $ [...] соответствует

  • Что касается $, описание мне более неясно:

$ [...] соответствует в конце целевой строки, а также до конца строки новой строки. Последнее является обычным, чтобы позволить выражению типа s$ (якобы, чтобы соответствовать "строке, заканчивающейся на s"), чтобы соответствовать …s<NL>, строке, заканчивающейся на s, которая ограничена завершающей новой строкой.

Два других общих значения для $ должны совпадать только в конце целевого текста и совпадать перед любой новой строкой.

Последние два значения кажутся довольно симметричными c к описанным для ^, но как насчет завершающей строки новой строки , означающей?

Поиск [regex] "string-ending newline" дает только one , two * Результаты 1053 * и три на данный момент, и все они относятся к

$ Соответствует конечной позиции строки или позиции непосредственно перед строкой- окончание новой строки. В линейных инструментах это соответствует конечной позиции любой строки.

Ответы [ 4 ]

4 голосов
/ 08 марта 2020

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


Без /m

$ совпадений перед переводом строки в конце строки и в конце строки.

"abc\ndef\n" =~ /^abc$/           # Doesn't match at embedded line feed
"abc\ndef\n" =~ /^abc\n$/         # Doesn't match after embedded line feed
"abc\ndef\n" =~ /^abc\ndef$/      # Matches at string-ending line feed
"abc\ndef\n" =~ /^abc\ndef\n$/    # Matches at end of string

Это эквивалентно \Z, что эквивалентно (?=\n\z|\z).

С /m

$ соответствует перед переводом строки и в конце строки.

"abc\ndef\n" =~ /^abc$/           # Matches at embedded line feed
"abc\ndef\n" =~ /^abc\n$/         # Doesn't match after embedded line feed
"abc\ndef\n" =~ /^abc\ndef$/      # Matches at string-ending line feed
"abc\ndef\n" =~ /^abc\ndef\n$/    # Matches at end of string

Это эквивалентно (?=\n|\z).


\z используется, когда вы хотите точное совпадение.

/xyz\z/    # String ends with "xyz"

$ используется, когда вы хотите игнорировать перевод задней строки.

/xyz$/     # Line ends with "xyz". The string might end with a line feed.

Например,

"jkl"   =~ /^jkl$/     # Matches at end of string
"jkl"   =~ /^jkl\z/    # Matches at end of string

"jkl\n" =~ /^jkl$/     # Matches at string-ending line feed
"jkl\n" =~ /^jkl\z/    # Doesn't match at string-ending line feed

$ полезно, если вы сопоставляете строки, которые вы еще не набрали.

while (<>) {
   next if /^foo$/;
   ...
}

\z полезно в остальное время.


Примечание что другие движки регулярных выражений могут вести себя по-другому, даже те, которые Perl -подобны. Например, в JavaScript, $ без /m совпадает только конец строки.

3 голосов
/ 07 марта 2020

Утверждение нулевой ширины $ устанавливает положение в конце строки или перед разделителем строки прямо в конце строки (если есть).

Это будет более понятно с этими фрагментами кода в perl:

$str = 'abc
foo';
$str =~ s/\w+$/#/;
print "1. <" . $str . ">\n\n";

$str = 'abc
foo
';
$str =~ s/\w+$/#/;
print "2. <" . $str . ">\n\n";

$str = 'abc
foo

';
$str =~ s/\w+$/#/;
print "3. <" . $str . ">\n\n";

Это сгенерирует этот вывод:

1. <abc
#>

2. <abc
#
>

3. <abc
foo

>

Как вы можете видеть, что $ соответствует случаям 1 и 2, потому что $ совпадает в конце строки ( case 1 ) или до разрыва строки прямо в конце ( case 2 ). Однако case 3 остается бесподобным, потому что разрыв строки не находится в конце строки.

0 голосов
/ 08 марта 2020

Пожалуйста, посмотрите, поможет ли следующий код в разъяснении значения $ в регулярном выражении, \n, добавленного для сравнения

use strict;
use warnings;
use feature 'say';

my $str = 'abc
foo
bar
';

my $str_test;

$str_test = $str;
$str_test =~ s/(.+)$/[$1]/;
say '-' x 30;
say ' regex :: s/(.+)$/[$1]/';
say '-' x 30;
say $str_test;

$str_test = $str;
$str_test =~ s/(.+)$/[$1]/s;
say '-' x 30;
say ' regex :: s/(.+)$/[$1]/s';
say '-' x 30;
say $str_test;

$str_test = $str;
$str_test =~ s/\n/[NL]\n/s;
say '-' x 30;
say ' regex :: s/\n/[NL]\n/s';
say '-' x 30;
say $str_test;

$str_test = $str;
$str_test =~ s/\n/[NL]\n/g;
say '-' x 30;
say ' regex :: s/\n/[NL]\n/g';
say '-' x 30;
say $str_test;

Вывод

------------------------------
 regex :: s/(.+)$/[$1]/
------------------------------
abc
foo
[bar]

------------------------------
 regex :: s/(.+)$/[$1]/s
------------------------------
[abc
foo
bar
]
------------------------------
 regex :: s/\n/[NL]\n/s
------------------------------
abc[NL]
foo
bar

------------------------------
 regex :: s/\n/[NL]\n/g
------------------------------
abc[NL]
foo[NL]
bar[NL]
0 голосов
/ 07 марта 2020

смысл в том, что $ будет соответствовать обоим до (а) символа (ов) новой строки и в конце файла или строки ввода, которые могут заканчиваться или не заканчиваться (а) символы новой строки

...