正则表达式匹配特定数量的选项卡后的特定值

时间:2016-10-17 08:59:25

标签: regex perl

在制表符分隔的文本文件中,我想仅匹配第24个选项卡后面包含“1”值的行。
现在,我的正则表达式似乎与我想要的匹配,但在行不匹配时断开 你能帮我改进一下吗?

我的正则表达式:

/(?:.+?\t){24}1/  

样本输入:

INT E_63    0   0   u   Le  Le  DET:ART DET le  ??  ADJ SENT DET:ART NOM ADV    SENT DET NOM    1   ??  ??  ??  ??  ??  0   0   0   0   0   1   ??  ??  ??  ??  ??  ??  
INT E_63    0   0   u   Le  Le  DET:ART DET le  ??  ADJ SENT DET:ART NOM ADV    SENT DET NOM    1   ??  ??  ??  ??  ??  0   0   0   0   0   0   ??  ??  ??  ??  ??  ??  

(第一行应该匹配,第二行不应该。)

2 个答案:

答案 0 :(得分:3)

由于catastrophic backtracking.也匹配而且与标签字符匹配,因此正则表达式不起作用。再加上在具有嵌套量词的组之后有更多的子模式,并且没有^锚点,灾难性的回溯即将到来。

你需要的是一个否定的字符类[^\t]并将模式锚定在字符串的开头:

/^(?:[^\t]*\t){24}1/

请参阅regex demo

注意:要将1作为整个字词进行匹配,您可以考虑在其后面添加\b或前瞻(?!\S)

<强>详情:

  • ^ - 字符串的开头
  • (?:[^\t]*\t){24} - 24个序列
    • [^\t]* - 除了标签字符
    • 之外的0 +字符
    • \t - 标签字符
  • 1 - 1字符。

答案 1 :(得分:2)

而不是使用正则表达式,你可以拆分它,检查第23个索引处的第24列,然后使用条件。

#!/usr/bin/perl
use strict;
use warnings;

open (my $fh, "<", '/path/to/tab_delem_file') or die "Could not open file $!";

while(<$fh>){
  chomp;
  my @line = split/\t/, $_; #split on tab
  if ($line[23] == 1){
      #do something
  }
  else ($line[23] == 1){
      #do something else
  }
}