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

Tih*_*kov 1 regex perl

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

Value1 Value2 value3

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

m/(.*?) (.*?) (.*?)/m;
Run Code Online (Sandbox Code Playgroud)

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

gho*_*g74 8

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

@s = split /\s+/ , $line;
Run Code Online (Sandbox Code Playgroud)


JB.*_*JB. 7

这是怎么回事

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

 /.*? .*? .*?/
Run Code Online (Sandbox Code Playgroud)

意思.*?是"匹配任何字符(除了换行符),尽可能少地匹配任何字符."

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

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

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

如何避免它

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

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


cod*_*ict 5

放在$最后regex解决这个问题:

m/(.*?) (.*?) (.*?)$/m;
Run Code Online (Sandbox Code Playgroud)

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

m/(.*?) (.*?) (.*)/m;
Run Code Online (Sandbox Code Playgroud)


bri*_*foy 5

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

您要匹配的行有:

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

一旦描述了这种情况,就可以将其翻译成正则表达式.您可以从描述的字面翻译开始:

 my @values = /(\S+) (\S+) (\S+)/;
Run Code Online (Sandbox Code Playgroud)

自从您使用以来\S,捕获中的模式部分无法通过空白来匹配比您想要的更多.*.

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

 my @values = /(\S+)/g;
Run Code Online (Sandbox Code Playgroud)

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

 my @values = split /\s+/;
Run Code Online (Sandbox Code Playgroud)