Perl脚本中的Linux grep命令不起作用

cbjzeqam  于 2022-11-15  发布在  Perl
关注(0)|答案(2)|浏览(300)

我有一个grep命令,它在Linux命令提示符下工作:grep -Po 'rand_num=\K[^ ]*' log.txt这个命令在我的log.txt文件中打印rand_num=后面的数字。但是我需要在perl脚本中使用这个命令。我试过了

my $rand_number;
$rand_number = system("grep -Po 'rand_num=\K[^ ]*' log.txt");
print "Random number = $rand_number";

但是不行我试过$rand_number =grep -Po 'rand_num=\K[^ ]*' log.txt;也不行
有人能告诉我这里出了什么问题吗?怎么让它工作的?

7kqas0il

7kqas0il1#

一旦进入Perl脚本,就不需要到系统中运行外部命令(它使用Perl的regex!)--Perl可以做得非常好,甚至更好。
以下是一些方法。
打开一个文件,逐行阅读,从每一行中提取所需的短语

open my $fh, '<', $file or die "Can't open $file: $!";

my @random_numbers;
while (<$fh>) { 
    push @random_numbers, /rand_num=(\S+)/g;
}
close $fh;
say for @random_numbers;

或者一次读取所有行,然后将它们通过排序过滤器

open my $fh, '<', $file or die "Can't open $file: $!";

my @random_numbers = map { /rand_num=(\S+)/g } <$fh>;

close $fh;
say for @random_numbers;

我使用map从每一行中提取短语,因为grep将返回满足条件的整行。如果没有匹配,则返回空列表,“消失”到map的整个返回列表中,如果没有匹配,则“消失”到未初始化的数组中。这样,map就充当了过滤器。
如果一行可以有多个rand_num=NUM,那么上面的代码会从每一行的所有rand_num=NUM中获取(假定为†)数字,如果还假定文件名$file已经被读入脚本。
或者,使用“null”文件句柄(不需要文件名)

my @random_numbers;
while (<>) { ... }                    # same block as in first example

#  OR 

my @random_numbers = map { ... } <>;  # same block as in second example

如果在命令行上使用该文件名script.pl file调用该脚本,则为。
这是因为“magic”diamond运算符(<>)逐行读取命令行上提交的文件。尽管如此,如果脚本以script.pl file1 file2 ...运行,它将对所有这些文件执行上述操作。
也可以将整个文件读入一个字符串(“slurp”),然后使用它。当感兴趣的模式跨越多行时,这很有帮助。

use Path::Tiny;  # path()

my @rn = path($file)->slurp =~ /.../g;  # same regex as before

现在,正则表达式匹配被绑定到slurp方法返回的字符串,该字符串包含整个文件。由于这是在列表上下文中完成的,通过列表赋值将其强加给正则表达式,因此所有匹配都在列表中返回,该列表被赋值给@rn
我大胆地假设您的(every)脚本以

use warnings;
use strict;

对于featuresay,我们还需要use feature 'say';use,一个包含它的Perl版本或另一个包含它的大型框架。
†问题中的正则表达式匹配rand_num=后面的所有非空格字符,如果绝对确定这些字符只能是预期的数字,那就这样吧。
否则,可以更小心地使用只匹配实际数字的模式。或者,如上所述捕获,然后使用looks_like_numberScalar::Util检查它是否确实是数字

uhry853o

uhry853o2#

Perl将\K视为转义序列,并删除了system看到的实际字符串中的反斜杠。

system("grep -Po 'rand_num=\\K[^ ]*' log.txt");

也可以使用Perl的多种方法之一编写一个字符串,完全禁止反斜杠扩展。

system q(grep -Po 'rand_num=\K[^ ]*' log.txt);

这看起来可能很奇怪,如果您的编辑器不是为Perl设计的,它可能也不理解它(老实说,我很惊讶StackOverflow的代码高亮器能正确处理它)。但是q(...)等效于'...',只是您可以在前者内部使用单引号。

相关问题