问题描述
让我们看看 Perl 代码和结果:
$s = "a\nb\nc\n";
$s =~ s/^b/X/;
print $s;
a
b
c
$s = "a\nb\nc\n";
$s =~ s/^b/X/m;
print $s;
a
X
c
我认为Perl是对的,只有启用多行时,^才匹配中间新行后的位置。
让我们看看 Ruby:
$s = "a\nb\nc\n"
print $s.sub(/^b/,'X')
a
X
c
$s = "a\nb\nc\n"
print $s.sub(/^b/m,'X')
a
X
c
^ 匹配文本中间换行符后的位置,无论是否处于多行模式。
在我的一生中,我找不到定义多行选项将做什么的 Ruby 文档,它在哪里?
Ruby 也没有单行模式吗?
undefined group option: /(?s)^b/
/^b./s
会解析但它的行为不像 Perl(. 匹配新行)。
PS:我使用 Perl 5 和 Ruby 3.0 进行了测试。
解决方法
Ruby 和 Perl 的 /m
工作方式不同。
Ruby 的 /m
仅更改了 .
的行为。它相当于 Perl 的 /s
。
-
Ruby
匹配的字符/m
:将换行符视为与 . -
Perl
/s
:将字符串视为单行。也就是说,改变“。”匹配任何字符,甚至是通常不会匹配的换行符。
Perl 的 /m
改变了 ^
和 $
的行为。
- Perl
/m
:将匹配的字符串视为多行。即,将“^”和“$”从匹配字符串的首行开头和最后一行的结尾更改为匹配字符串中每一行的开头和结尾。
^
和 $
在 Ruby 中始终以这种方式工作。 Ruby 总是有效地拥有 Perl 的 /m
。
Ruby 和 Perl 都共享 \A
、\z
和 \Z
以匹配字符串的开头、字符串结尾或最后一个换行符之前。
哪个是正确的?也不是,他们做自己的事。 Perl 对 ^
和 $
的默认行为与 POSIX regular expressions 相同,但它们在其他方面不兼容。 Python 使用等效于 Perl 的多行和单行模式 (MULTILINE and DOTALL)。 Ruby 简化了 ^
和 $
的行为并使正则表达式更加明确。
另见
,我认为Perl是对的,只有启用多行时,^才匹配中间新行后的位置。
是的,没错。根据 man perlre
,section Metacharacters,^
锚点意味着:
匹配字符串的开头(或行,如果使用 /m)
让我们看看 Ruby: […] ^ 匹配文本中间换行符后的位置,无论是否处于多行模式。
也正确。根据{{3}}:
^
- 匹配行首
在我的一生中,我找不到定义多行选项将做什么的 Ruby 文档,它在哪里?
它在the documentation of the Regexp
class,section Anchors:
/pat/m
- 将换行符视为与 .
Ruby 也没有单行模式吗?
在 Ruby 中,您可以通过在模式前加上破折号 -
来停用模式。因此,如果您当前处于多行模式,并且想回到单行模式,则不需要单独的模式。您可以再次使用 -m
关闭多行模式。