【问题标题】:How can I extract groups of non-whitespace from a line in Perl?如何从 Perl 中的一行中提取非空白组?
【发布时间】:2011-02-10 11:45:24
【问题描述】:

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

值1 值2 值3

我有一个正则表达式来匹配它们

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

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

【问题讨论】:

    标签: regex perl


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      发生了什么

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

       /.*? .*? .*?/
      

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

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

      换句话说,我们在.*? 组后面有一个空格,这使它与您想要的匹配。否则它会很高兴地在零个字符处停止匹配。

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

      避免它的方法

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

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

      【讨论】:

        【解决方案3】:

        regex 的末尾加上一个$ 来解决这个问题:

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

        或者你可以制作最后一部分greedy:

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

        【讨论】:

          【解决方案4】:

          在这种情况下,您并不想使用* 量词,也不想让这些量词变得贪婪。正则表达式的诀窍是尽可能具体地描述模式。

          你要匹配的行有:

          1. 一些非空格
          2. 一些空格
          3. 再重复两次

          一旦您描述了情况,您就可以将其翻译成正则表达式。您可以从描述的直译开始:

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

          由于您使用了\S,因此捕获中的模式部分无法通过空格来匹配超出您预期的范围,就像.* 一样。

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

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

          你也可以考虑反过来。您可以使用split 丢弃空白,而不是捕获非空白:

           my @values = split /\s+/;
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-01-07
            • 1970-01-01
            • 1970-01-01
            • 2023-03-16
            • 2011-05-04
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多