多个grep(带有正则表达式)函数在Perl脚本中不起作用

时间:2016-05-10 20:23:24

标签: regex perl

现在遇到脚本问题。 试图过滤掉文件的某些部分并将它们放入标量中。这是代码。

 @value = (grep {m/(III[ABC])/g and m//g }<$fh>)
 print @value;
 @value = (grep { m/[012]iii/g}(<$fh>));
 print @value;

当我运行第一个grep时,值会显示在打印参数中。但是当我运行第二个grep时。第二个打印语句不打印任何内容。添加第二个grep,取消第一个grep的有效性吗?

我知道第一次和第二次grep工作,因为即使我评论了第一个grep。第二个grep函数工作。 我真正想要做的就是过滤掉多个不同的单个阵列的信息。我真的很困惑如何解决这个问题,因为我打算在脚本中添加更多的grep。

2 个答案:

答案 0 :(得分:4)

<$fh>上的第一次读取到达文件的末尾。然后第二次调用无需阅读。因此,如果你注释掉第一个,那么这并不会发生,第二个就会起作用。

下面的代码添加到同一个数组中。如果需要,请更改为注释掉的代码。正则表达式是简化的,因为它不需要注释而它不会影响实际问题。请把它放回原来的样子,如果那是你的真实含义。

您可以在读完所有行后回放文件句柄

my @vals = grep { /III[ABC]/ } <$fh>;
seek $fh, 0, 0;
# ready for reading again from the beginning
push @vals, grep { /[012]iii/ } <$fh>;
#or:  my @vals_2 = grep { /[012]iii/ } <$fh>;

或者您可以将所有行读入数组,然后然后重复处理。

my @original = <$fh>;

my @vals = grep { /III[ABC]/ } @original;
push @vals, grep { m/[012]iii/ } @original; 
# or assign to a different array

如果您不需要按照这样的顺序存储这些结果,那么逐行读取文件并进行处理和添加会更有效率。

<强>更新

我简化了最初发布的正则表达式,以便专注于手头的问题,因为块内的确切条件与它无关。请参阅下面的注释。感谢ikegami提出并解释//&#34; 重复上次成功的查询&#34;。

  • m//g很棘手,我将其删除了。
  • grep检查条件并在条件评估为真时传递一条直线。在这样的标量上下文中,/.../g修饰符的效果是一个非常不同的故事,已删除。
  • 由于与上述相同的原因,捕获()是不需要的(过量)。
  • 清理语法有助于提高可读性,删除m/

有关正则表达式的说明

在标量上下文中/.../g修饰符按perlrequick执行以下操作:

  

对字符串的连续匹配将// g从匹配跳转到匹配

空字符串模式m//g也具有很明显的效果,如上所述。

总之,这些在我的测试中产生了非平凡的结果,需要精神追踪才能理解。我把它们从这里的代码中删除了,因为它们会引起一个问题,即它们是否是故意的诡计或微妙的错误,从而分散了实际的问题 - 它们完全没有影响。

答案 1 :(得分:2)

  • 我不知道您对g修饰符的看法,但这里没有任何意义。

  • 我不知道你的想法是什么//(与空模式相匹配),但这里没有任何意义。

  • 在列表上下文中,<$fh>返回文件中的所有剩余行。第二次评估它时,它不返回任何内容,因为您第一次评估它时已经到达文件的末尾。

修正:

my @lines = <$fh>;
my @values1 = grep { /III[ABC]/ && /.../ } @lines;
my @values2 = grep { /[012]iii/ } @lines;

当然,请将...替换为您在那里使用的内容。