从我的Perl代码中,我想执行系统调用
$grepp = `grep 'output\s+reg' $file`;
但我保留
Unrecognized escape \s passed through at
您能帮助我理解此错误吗?
答案 0 :(得分:1)
在双引号和其他类似的字符串文字中,例如反引号,\
对Perl来说很重要。
\
后跟非单词字符(例如\
或其他符号)只会导致转义字符。
\
后跟一些单词字符具有特殊含义(例如\n
导致换行,\x0A
也是如此)。当\
后跟一个Perl没有意义的单词字符(例如\s
)时,您会收到该警告,因为您的代码不向前兼容。通过转义\
使代码向前兼容,可以避免警告。
my $grepp = `grep 'output\\s+reg' $file`; # Executes: grep 'output\s+reg' some file.txt
除了您所问的问题之外,该代码还有两个主要问题。
第一个主要是代码注入错误。您正在将文本(文件名)插入代码(shell命令)而不进行任何形式的转换。如果文件名包含任何外壳程序元字符(例如空格,(
,;
等),则此操作将失败,并且恶意行为者可能会利用此错误来执行破坏性命令。>
String::ShellQuote的shell_quote
可用于避免此问题。
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote('grep', 'output\s+reg', $file);
my $grepp = `$cmd`;
您还可以避免使用以下模块并避免创建外壳:
open(my $pipe, '-|', 'grep', 'output\s+reg', $file);
my $grepp = '';
$_ .= $grepp while <$pipe>;
close($pipe);
第二个主要问题是您提供的模式并不意味着您认为的那样。 grep
默认使用的正则表达式模式语言与Perl完全不同。您需要以下之一:
output[[:space:]]\+reg # Without -E or -P
或
output\s\+reg # Without -E or -P. Less portable
或
output\s+reg # With -E or -P
因此,以下是最终代码:
use String::ShellQuote qw( shell_quote );
my $cmd = shell_quote('grep', '-E', 'output\s+reg', $file);
my $grepp = `$cmd`;
当然,人们不得不怀疑为什么您执行grep
实用程序而不是自己在Perl中执行搜索。