为什么这两个命令的输出不同?
cat config.xml|perl -ne 'print $1,"\n" if /([0-9\.]+):161/'
cat config.xml|perl -ne "print $1,"\n" if /([0-9\.]+):161/"
Run Code Online (Sandbox Code Playgroud)
首先按预期打印出匹配组,而秒打印整行.
我看到你的命令有两个主要问题.
首先,双引号允许shell插值,并将$1用于shell变量并替换.由于它不太可能存在,它将被替换为空字符串.所以不是print $1,你得到print,这是简写print $_,也可能是整行打印的原因.
其次,你的命令中有未转义的双引号,所以你实际上是将三个字符串传递给Perl:
print ,
\n
if /(....)/
Run Code Online (Sandbox Code Playgroud)
至于为什么或如何使用你的shell,我不知道,因为我无法访问你的操作系统,也不知道它是哪一个.在Windows中,我得到n(Unquoted string "n" may clash with future reserved word at -e line 1.)的Perl裸字警告,这意味着它\n被解释为一个字符串.现在,这是棘手的部分.我们得到的是:
print , \n if /.../
Run Code Online (Sandbox Code Playgroud)
这意味着它\n不再是一个参数print,它是一个后来的语句,print它在void上下文中,所以它被忽略了.我们可以通过这个警告(我必须在我的shell中伪造)看到这个:
Useless use of single ref constructor in void context at -e line 1.
Run Code Online (Sandbox Code Playgroud)
(请注意,您不会收到这些警告,因为您不使用警告 - -w开关)
所以我们留下的是
print if /.../
Run Code Online (Sandbox Code Playgroud)
这正是您所描述的行为的代码:它在找到匹配项时打印整行.
你可以做些什么来显示你的shell中的问题是将-MO=Deparse开关添加到你的单行,如下所示:
C:\perl>perl -MO=Deparse -ne"print ,"\n" if /a/"
LINE: while (defined($_ = <ARGV>)) {
print($_), \'n' if /a/;
}
-e syntax OK
Run Code Online (Sandbox Code Playgroud)
现在我们可以清楚地看到print语句与换行符分开,并且换行符是对字符串的引用.
解:
但是,您的代码还有其他问题,如果做得好,您可以避免所有shell困难.首先,你有一个UUOC(无用的猫).-n在命令行上使用开关时,可以为perl提供文件参数.其次,您不需要为此使用变量,您只需打印正则表达式的返回值:
perl -nlwe 'print for /(...)/' config.xml
Run Code Online (Sandbox Code Playgroud)
该-l开关将为您处理换行,在这种情况下,为打印添加换行符.该for避免打印空场比赛是必要的.