Par*_*roX 4 regex bash perl grep
我正在写一些东西,允许用户搜索他们的日志.目前我有这个,其中$'{SEARCH'}是他们正在搜索的字符串.
open(COMMAND, "grep \"$in{'SEARCH'}\" /home/$palace/palace/logs/$logfile | tail -n $NumLines |");
$f = <COMMAND>;
if ($f) {
print $Title;
print "<div id=log>\n";
do { print $f."<br>";} while ($f = <COMMAND>);
print "</div>\n";
} else {print $Error; }
close(COMMAND);
Run Code Online (Sandbox Code Playgroud)
但是我注意到他们可以通过使用双引号(")或反斜杠来轻易地欺骗脚本和grep命令错误.因此我添加了这段代码:
$in{'SEARCH'} =~ s|\\|\\\\|g;
$in{'SEARCH'} =~ s|"|\Q\"\E|g;
open(COMMAND, "grep \"$in{'SEARCH'}\" /home/$palace/palace/logs/$logfile | tail -n $NumLines |");
$f = <COMMAND>;
if ($f) {
print $Title;
print "<div id=log>\n";
do { print $f."<br>";} while ($f = <COMMAND>);
print "</div>\n";
} else {print $Error; }
close(COMMAND);
Run Code Online (Sandbox Code Playgroud)
但是,我仍然遇到问题.grep命令不喜欢\在其搜索中给出错误
grep"\\"/home/test/palace/logs/chat.log
grep:尾随反斜杠
我是否应该继续尝试使用grep命令,如果是这样,什么是一个好的Perl函数,有助于剥离有助于grep命令的奇怪字符,比如说"成为"等等.或者,改为乱搞我应该只使用Perl代码来完成同样的事情,即使我已经读过它不会像grep一样快?
更新:7-5-2009美国东部时间下午5:20
许多人贡献了代码,特别是那些试图比系统grep更快的代码.截至目前,它仍然是最快的.以下是基准测试的结果:
使用系统grep:
Top of file: 1 wallclock secs ( 0.00 usr 0.01 sys + 0.13 cusr 0.15 csys = 0.29 CPU)
Bottom of file: 1 wallclock secs ( 0.00 usr 0.00 sys + 0.21 cusr 0.18 csys = 0.39 CPU)
Run Code Online (Sandbox Code Playgroud)
使用Hypneks示例(推和移):
Top of file: 4 wallclock secs ( 3.78 usr + 0.19 sys = 3.97 CPU)
Bottom of file: 4 wallclock secs ( 3.86 usr + 0.19 sys = 4.05 CPU)
Run Code Online (Sandbox Code Playgroud)
使用我的perl示例(使用reverse命令):
Top of file: 6 wallclock secs ( 4.76 usr + 1.45 sys = 6.21 CPU)
Bottom of file: 5 wallclock secs ( 3.93 usr + 1.44 sys = 5.37 CPU)
Run Code Online (Sandbox Code Playgroud)
使用我的文件:: ReadBackwards:
Top of file:11 wallclock secs (11.20 usr + 0.11 sys = 11.31 CPU)
Bottom of file: 1 wallclock secs ( 0.59 usr + 0.01 sys = 0.60 CPU)
Run Code Online (Sandbox Code Playgroud)
使用xcramps示例(内置grep):
Top of file: 9 wallclock secs ( 8.04 usr + 0.47 sys = 8.51 CPU)
Bottom of file: 8 wallclock secs ( 8.16 usr + 0.43 sys = 8.59 CPU)
Run Code Online (Sandbox Code Playgroud)
我同意Ry4an认为与Perl合作可能是明智的.
如果你想修复你的代码,你需要(应该)在你不希望shell搞乱的参数周围使用单引号 - 而不是双引号.例如,反引号或' $(...)'符号将在双引号内执行命令,' ${variable}'等等将被扩展.处理所有符号太像是艰苦的工作; 使用单引号更简单.请注意,嵌入的单引号需要用序列" '\''" 替换(这很有趣!); 双引号只是用你替换单引号的四个字符(假设字符串作为一个整体嵌入单引号).第一个引号关闭当前引用的字符串; 反斜杠,单引号意味着单字引号; 最后一个单引号开始一个新的单引号字符串.您不需要转义任何其他字符.
拿你的代码:
my $search = $in{SEARCH};
$search =~ s/'/'\\''/g;
open(COMMAND, "grep '$search' /home/$palace/palace/logs/$logfile | tail -n $NumLines |");
$f = <COMMAND>;
if ($f)
{
print $Title;
print "<div id=log>\n";
do { print $f."<br>";} while ($f = <COMMAND>);
print "</div>\n";
}
else
{
print $Error;
}
close(COMMAND);
Run Code Online (Sandbox Code Playgroud)