在What regular expressions can never match? /$./
作为回复。我玩了一下,发现以下两行代码产生不同的输出。第二场比赛,但第一场比赛没有。任何人都可以解释原因吗?
$ printf 'a\nb\n' | perl -0777 -ne 'print if m/$./m'
$ perl -0777 -e '$_="a\nb\n"; print if m/$./m'
另外,请注意添加<>在下面导致匹配失败:
$ printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; say $b =~ m/$./m'
$ printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; <>; say $b =~ m/$./m'
(也就是说,第一次打印'1',第二次打印空行)
答案 0 :(得分:9)
打开警告提供了一个关于原因的线索:
$ printf 'a\nb\n' | perl -0777 -w -e 'use feature qw/say/; $b = "a\nb\n"; say $b =~ m/$./m' Use of uninitialized value $. in regexp compilation at -e line 1. 1
您在正则表达式中使用了未定义的值。序列$.
refers to the special variable for the line number of the last-accessed file handle。 不指定“行尾后跟任何字符”的正则表达式。由于您还没有访问任何文件,它仍然是undef,所以正则表达式是空的。当您使用-n
选项时,它会有效地将该计划的其余部分包含在while (<>) { ... }
中,因此您在<>
中阅读1
并以$.
结尾,因为你读过一行。
当您在第二次尝试中说<>
时,您已经访问了stdin文件句柄。现在正则表达式为m/1/m
,与输入字符串不匹配。
答案 1 :(得分:6)
正则表达式中的$.
被解析为特殊变量$.
($INPUT_LINE_NUMBER
)的值,而不是“行尾后跟任何字符。”
另请注意,/m
修饰符会将$
的含义从字符串末尾的匹配更改为匹配字符串中任意位置的行结尾。请参阅perlre中的Modifiers。这意味着可以在它之后有一些东西(使用适当的修饰符):
say "a\nb\n" =~ m/$ ./msx;
打印“1”。 /x
修饰符允许使用嵌入的空格,因此我们可以将$
与.
分开,以避免将其解释为变量。
答案 2 :(得分:5)
这段代码为我打印“破管”,因为perl不希望这里有任何输入。它还使用未定义的变量$.
(如果你将-w
切换到perl,你会看到它。此变量$.
表示当前行号,然后按<...>
读取行。这就是为什么在这个例子中未定义的原因:
## matching pattern will look like m//m
printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; say $b =~ m/$./m'
以下代码读取管道数据,但不匹配,因为$.
在<>
之后变为等于1。匹配模式变为m/1/m
:
## matching patter will be m/1/m, which is not found in $b value
printf 'a\nb\n' | perl -0777 -e '$b = "a\nb\n"; <>; say $b =~ m/$./m'
<强>更新强>
使用m'$.'m
或m/$ ./mx
(感谢Michael Carman)禁用变量插值。
答案 3 :(得分:0)
在第一个例子中,我认为这是因为-n开关。换句话说
printf 'a\nb\n' | perl -0777 -ne 'print if m/$./m'
导致$ _第一次通过循环获得值a\n
,第二次b\n
使得m/$./m
无法匹配。而/ m $匹配第二个示例中的\ n,这就是匹配的原因。
在后两个例子中,我仍然在研究:)
编辑:哇我完全错了,我想你也可能。问题是{{1}} 不是行尾,后跟通配符,而是变量$。插值为正则表达式。糟糕!