2016-03-31 54 views
3

我想寫一個正則表達式,它會讓我在這個列表中的第21個字段的內容中以I開頭的行,只要該字段包含這種格式的數字NNN-NNNNNN(如001-123456):如何寫沒有災難性回溯的這個正則表達式

T|112||  |    | |AZ  |D   |1 |  1| 
I| 10|ACAA   |BY CORD EACH    |  10.00-|  .99 |  |  .36 |1 |  1|D   |I|CO |BTE |N| |  .00 |  .00 |15 |1 |001-123456  |ACAA 
I| 20|LEES03  |TINTED OZ    |  2.00-|  6.50 |  |  4.48 |1 |  1|D   |I|FL |LTGE |N| |  .00 |  .00 |45 |1 |001-234555  |JEE 
I| 20|LEES03  |TINTED OZ    |  2.00-|  6.50 |  |  4.48 |1 |  1|D   |I|FL |LTGE |N| |  .00 |  .00 |45 |1 |    |JEE 
I| 20|LEES03  |TINTED OZ    |  2.00-|  6.50 |  |  4.48 |1 |  1|D   |I|FL |LTGE |N| |  .00 |  .00 |45 |1 |001-234552  |JEE 

下面是簡單的regex,我使用,有我在拍攝第二捕獲組在該領域的內容:

^I(\|.*?){20}(\d{3}-\d{6}) 

我已閱讀關於災難性的回溯,但我的正則表達式技能是有限的,我不明白如何寫這個正則表達式,以便我不會得到災難性的回溯。

幫助將不勝感激。

+0

當你知道它有格式'NNN-nnnnnn'爲什麼不乾脆用'\ d {3} - \ d {6}'? –

+1

@noob我_am_使用它,但我只對第21個字段感興趣 - 我不想在任何其他字段中匹配此字符串。 – Zek

+0

由於您其他字段沒有使用那個模式的數字就會匹配第21個字段。 –

回答

5

您可以通過使用否定模式避免災難性回溯

^I(?:\|[^|]*){20}(\d{3}-\d{6}) 

[^|]*匹配0或多個字符不屬於|

RegEx Demo

5

海事組織,更好的辦法是由分裂管道上的字符串,然後檢查第一個和第21個字段。

perl -F'\|' -anE'say $& if $F[0] eq "I" && $F[20]=~/\S+/' file 

例如在腳本:與自動分割參數-a命令行的例子

use strict; 
use warnings; 
use feature qw(say); 

my @F; 
while(<DATA>) { 
    @F = split /\|/; 
    say $1 if $F[0] eq 'I' && $F[20] =~ /(\d+-\d+)/ 
} 

__DATA__ 
T|112||  |    | |AZ  |D   |1 |  1| 
I| 10|ACAA   |BY CORD EACH    |  10.00-|  .99 |  |  .36 |1 |  1|D   |I|CO |BTE |N| |  .00 |  .00 |15 |1 |001-123456  |ACAA 
I| 20|LEES03  |TINTED OZ    |  2.00-|  6.50 |  |  4.48 |1 |  1|D   |I|FL |LTGE |N| |  .00 |  .00 |45 |1 |001-234555  |JEE 
I| 20|LEES03  |TINTED OZ    |  2.00-|  6.50 |  |  4.48 |1 |  1|D   |I|FL |LTGE |N| |  .00 |  .00 |45 |1 |    |JEE 
I| 20|LEES03  |TINTED OZ    |  2.00-|  6.50 |  |  4.48 |1 |  1|D   |I|FL |LTGE |N| |  .00 |  .00 |45 |1 |001-234552  |JEE 
+3

這是解決問題的正確方法。正則表達式來解析分隔文件是痛苦的。 – Sobrique