我正在编写一个必须从文件中获取值的程序.在文件中,每一行表示一个实体.每个实体都有三个值.例如:
Value1 Value2 value3
我有一个正常的表达来匹配他们
m/(.*?) (.*?) (.*?)/m;
Run Code Online (Sandbox Code Playgroud)
但似乎第三个价值从未匹配过!匹配第三个值的唯一方法是在文件中添加另一个值,并在表达式中添加另一个"匹配括号".但这并不能让我满意.
在你想到用正则表达式做事之前,想一想没有它就能解决它.如果你想获得实体,更简单的方法是将它们分开.返回列表的元素将是您想要的.
@s = split /\s+/ , $line;
Run Code Online (Sandbox Code Playgroud)
让我们暂时简化一下你的正则表达式的捕获,因为它不对发生的事情负责.因此你的正则表达式是这样的:
/.*? .*? .*?/
Run Code Online (Sandbox Code Playgroud)
意思.*?是"匹配任何字符(除了换行符),尽可能少地匹配任何字符."
在这种情况下,第一个.*?会尝试匹配字符串中的零个字符,然后在下一个正则表达式元素(空格)上失败.它将再次尝试匹配字符串中的一个,两个......字符,并且当下一个字符是实际空格时将首先成功.
换句话说,我们在.*?小组之后有一个空间,使其符合您的要求.否则它会很乐意停止匹配零字符.
这正是你的第三场比赛正在发生的事情.由于你的正则表达式在那里结束,空匹配确实满足正则表达式组,并且是首选匹配.
正如其他答案所说,可能的解决方案包括:
split (预期语义IMO的最佳转录).*而不是.*?)$如果线在那里结束\S)而不是任何字符(.).这适用于greedy(\S*)或nongreedy(\S*?)匹配.放在$最后regex解决这个问题:
m/(.*?) (.*?) (.*?)$/m;
Run Code Online (Sandbox Code Playgroud)
或者你可以做最后一部分greedy:
m/(.*?) (.*?) (.*)/m;
Run Code Online (Sandbox Code Playgroud)
*在这种情况下,你真的不想使用量词,并且你不想让那些量词变得贪婪.正则表达式中的技巧是尽可能具体地描述模式.
您要匹配的行有:
一旦描述了这种情况,就可以将其翻译成正则表达式.您可以从描述的字面翻译开始:
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)
| 归档时间: |
|
| 查看次数: |
628 次 |
| 最近记录: |