/m 和 /s 修饰符和字符类的 Perl 文档可以从连接点和添加更多示例中受益,我将在这里尝试。
不管/m 和/s 修饰符如何,字符类可以匹配换行符。这就是[^B]* 匹配\n 并得到扩展的原因在您的情况下通过多个换行符。实际上,您可以指定一个明确包含 ([\n]) 或不包含 ([^\n]) 换行符的字符类。除了换行符(\n),还有一个非换行符(\N)。
/s 修饰符只改变. 的行为(它允许. 匹配换行符)。它不会改变任何其他字符类的行为。
单独使用/m 和/s 修饰符可以获得明显不同的行为,如下面的示例所示。此行为已记录在案,因此是可预测的,但并不总是直观的。我通常一起使用这些修饰符
(/ms),并发现它使我的代码更加直观和可维护。这样,我不必每次都考虑换行匹配行为。事实上,作为习惯,我通常在我自己的代码中的大多数正则表达式中使用 /xms 修饰符,/x 使代码更具可读性和可维护性 (Conway (2005), p. 236-241, Vromans ( 2006))。
参考:
perlrecharclass - Perl Regular Expression Character Classes: Backslash sequences
\N Match a character that isn't a newline.
perlreref - Perl Regular Expressions Reference: CHARACTER CLASSES
\N A non newline (when not followed by '{NAME}';;
not valid in a character class; equivalent to [^\n]; it's
like '.' without /s modifier)
perlre - Perl regular expressions: Modifiers
m
将匹配的字符串视为多行。也就是说,将"^"和"$"从匹配字符串第一行的开头和最后一行的结尾更改为匹配字符串中每一行的开头和结尾。
s
将字符串视为单行。也就是说,更改 "." 以匹配任何字符,甚至是换行符,通常它不会匹配。
作为/ms 一起使用,它们让"." 匹配任何字符,同时仍然允许“^”和“$”分别匹配字符串中换行符之后和之前。
(注意它没有提到/m 或/s 改变了'.' 以外的字符类,所以我们可以从这里推断它们没有被改变)
使用/xms 修饰符:
- 始终使用 /x 标志。
- 始终使用 /m 标志。
- 始终使用 /s 标志。
(Conway (2005),第 236-241 页,Vromans (2006))
Damian Conway (2005) Perl 最佳实践:开发可维护代码的标准和风格。奥莱利媒体。 https://www.amazon.com/Perl-Best-Practices-Developing-Maintainable/dp/0596001738/
Perl 最佳实践:参考指南:https://www.squirrel.nl/pub/PBP_refguide-1.02.00.pdf
示例:
use strict;
use warnings;
use feature qw( say );
my @strings = (
"abcd\n", # single-line string
"abcd\nabcd\n", # multi-line string (first string repeated twice)
"abXd\nabcd\n", # multi-line string, same as above, but missing first 'c'
"abcd\nabXd\n", # multi-line string, same as above, but missing first 'c'
);
my @regexes = ( '^([^c]*)(c.*?)$' );
foreach my $string ( @strings ) {
foreach my $regex ( @regexes ) {
my @matches;
say "\n###";
say "# \$string='$string'; \$regex='$regex'";
@matches = map { "'$_'" } $string =~ /$regex/;
say "regex_modifiers=''; \@matches=@matches;";
@matches = map { "'$_'" } $string =~ /$regex/m;
say "regex_modifiers='m'; \@matches=@matches;";
@matches = map { "'$_'" } $string =~ /$regex/s;
say "regex_modifiers='s'; \@matches=@matches;";
@matches = map { "'$_'" } $string =~ /$regex/ms;
say "regex_modifiers='ms'; \@matches=@matches;";
}
}
输出:
###
# $string='abcd
'; $regex='^([^c]*)(c.*?)$'
regex_modifiers=''; @matches='ab' 'cd'; # ok
regex_modifiers='m'; @matches='ab' 'cd'; # /m, /s modifiers do not matter in single-line string
regex_modifiers='s'; @matches='ab' 'cd'; # /m, /s modifiers do not matter in single-line string
regex_modifiers='ms'; @matches='ab' 'cd'; # /m, /s modifiers do not matter in single-line string
###
# $string='abcd
abcd
'; $regex='^([^c]*)(c.*?)$'
regex_modifiers=''; @matches=; # '.' does not match newline, cannot reach end of string
regex_modifiers='m'; @matches='ab' 'cd'; # '$' matches first newline
regex_modifiers='s'; @matches='ab' 'cd
abcd'; # '.' matches newline, so the end of string is reached
# and '$' matches it.
regex_modifiers='ms'; @matches='ab' 'cd'; # non-greedy '.*?' causes '$' to match the first newline
###
# $string='abXd
abcd
'; $regex='^([^c]*)(c.*?)$'
regex_modifiers=''; @matches='abXd
ab' 'cd'; # [^c] matches newline, /m, /s modifiers do not matter
regex_modifiers='m'; @matches='abXd
ab' 'cd'; # [^c] matches newline, /m, /s modifiers do not matter
regex_modifiers='s'; @matches='abXd
ab' 'cd'; # [^c] matches newline, /m, /s modifiers do not matter
regex_modifiers='ms'; @matches='abXd
ab' 'cd'; # [^c] matches newline, /m, /s modifiers do not matter
###
# $string='abcd
abXd
'; $regex='^([^c]*)(c.*?)$'
regex_modifiers=''; @matches=; # '.' does not match newline, cannot reach end of string
regex_modifiers='m'; @matches='ab' 'cd'; # matches second line
regex_modifiers='s'; @matches='ab' 'cd
abXd'; # '.' matches newline, so the end of string is reached
# and '$' matches it.
regex_modifiers='ms'; @matches='ab' 'cd'; # non-greedy '.*?' causes '$' to match the first newline