如何从Perl中的一行中提取非空格组?

时间:2010-04-21 07:54:37

标签: regex perl

我正在编写一个必须从文件中获取值的程序。在文件中,每一行表示一个实体。每个实体都有三个值。例如:

  

Value1 Value2 value3

我有一个正常的表达来匹配他们

m/(.*?) (.*?) (.*?)/m;

但似乎第三个值从未匹配过!匹配第三个值的唯一方法是在文件中添加另一个值,并在表达式中添加另一个“匹配括号”。但这并不能让我满意。

4 个答案:

答案 0 :(得分:8)

在你想到用正则表达式做事之前,想一想没有它就能解决它。如果你想获得实体,更简单的方法是将它们分开。返回列表的元素将是您想要的。

@s = split /\s+/ , $line;

答案 1 :(得分:7)

发生了什么

让我们简化一下你的正则表达式的捕获,因为它不对发生的事情负责。因此你的正则表达式是这样的:

 /.*? .*? .*?/

.*?的含义是“匹配任何字符(换行符除外),尽可能少地匹配任何字符。”

在此上下文中,第一个.*?将尝试匹配字符串中的零个字符,然后在下一个正则表达式元素(空格)上失败。它将再次尝试匹配字符串中的一个,两个......字符,并且当下一个字符是实际空格时将首先成功。

换句话说,事实上我们在.*?组后面有一个空格,使其符合您的要求。否则它会很乐意停止匹配零字符。

这正是你的第三场比赛所发生的事情。由于正则表达式在那里结束,因此空匹配确实满足正则表达式组,并且是首选匹配。

避免它的方法

正如其他答案所说,可能的解决方案包括:

  • split(预期语义IMO的最佳转录)
  • 使最后一次捕获变得贪婪(.*而不是.*?
  • 在最后一次捕获后添加一些东西(匹配的东西)。 $如果该行结束
  • 匹配非空格(\S)而不是任何字符(.)。这适用于贪婪(\S*)或不同意(\S*?)匹配。

答案 2 :(得分:5)

$的末尾添加regex来解决此问题:

m/(.*?) (.*?) (.*?)$/m;

或者,您可以制作最后一部分greedy

m/(.*?) (.*?) (.*)/m;

答案 3 :(得分:5)

在这种情况下,您真的不想使用*量词,并且您不希望让这些量词变得贪婪。正则表达式中的技巧是尽可能具体地描述模式。

您要匹配的行有:

  1. 一些非空白
  2. 一些空白
  3. 再重复两次
  4. 一旦您描述了这种情况,就可以将其翻译成正则表达式。您可以从描述的字面翻译开始:

     my @values = /(\S+) (\S+) (\S+)/;
    

    由于您使用了\S,因此捕获中的模式部分无法通过空格来匹配比您想要的更多,因为.*可以。

    你重复了部分模式,所以你可以压缩它。由于您只是捕获空白组,所以请改为全局匹配:

     my @values = /(\S+)/g;
    

    你也可以考虑反过来。您可以使用split

    丢弃空格,而不是捕获非空格
     my @values = split /\s+/;