2014-01-10 29 views
0

我試圖用perl正則表達式來解析文本文件。下面是一個示例數據集:Perl正則表達式:匹配給定匹配後的字符串的第一個實例

"Field1", "Field2", "Field3", "Field4", "Field5" 
"val1-1", "\\path\to\val1-2.txt", "val1-3", "\\path\to\val1-4.ini", "val1-5.txt" 
"val2-1", "val2-2", "\\path\to\val2-3.txt", "\\path\to\val2-4.ini", "val2-5.txt" 
"\\path\to\val3-1.txt", "val3-2", "val3-3", "\\path\to\val3-4.ini", "val3-5.txt" 

對於每行文本,我試圖匹配.txt文件名的第一個實例;上述數據集中粗體的子串。

我想這會工作:

while(<INFILE>) { 
    if(m/\\(.*?\.txt)"/) { 
     print "$1\n"; 
    } 
} 

輸出:

\path\to\val1-2.txt 
\path\to\val2-3.txt 
\path\to\val3-1.txt 

,但它並沒有因爲這將匹配的完整路徑,而不僅僅是文件名。

現在這個工程:

while(<INFILE>) { 
    if(my @matches = $_ =~ m/(.*?)"/g) { 
     foreach (@matches) { 
      print "$1\n" if(m/.*\\(.*?\.txt)/); 
     } 
    } 
} 

輸出:

val1-2.txt 
val2-3.txt 
val3-1.txt 

但我想一定有辦法用一個單一的匹配表達式做到這一點?

回答

1

如何:

my $re = qr~\\([^\\"]+)"~; 
while(<DATA>) { 
    chomp; 
    if(my @m = /$re/g) { 
     say "@m"; 
    } 
} 

__DATA__ 
"Field1", "Field2", "Field3", "Field4", "Field5" 
"val1-1", "\\path\to\val1-2.txt", "val1-3", "\\path\to\val1-4.ini", "val1-5.txt" 
"val2-1", "val2-2", "\\path\to\val2-3.txt", "\\path\to\val2-4.ini", "val2-5.txt" 
"\\path\to\val3-1.txt", "val3-2", "val3-3", "\\path\to\val3-4.ini", "val3-5.txt" 

輸出:

val1-2.txt val1-4.ini 
val2-3.txt val2-4.ini 
val3-1.txt val3-4.ini 

如果你只想要第一個txt文件,這樣做:

my $re = qr~\\([^\\"]+\.txt)~; 
while(<DATA>) { 
    chomp; 
    /$re/ && say $1; 
} 
+0

OP說他想要第一個'.txt',所以我猜不需要'.ini'。引用的正則表達式是個好主意。 :) – simbabque

+0

@simbabque:不確定,但我編輯了我的答案。 – Toto

+0

@simbabque是正確的:不需要.ini。下面是我如何翻譯你的正則表達式,以防萬一也幫助別人:'[^ \\「]'==>匹配任何不是\或」。 '+'==>至少匹配一次。所以'[^ \\「] + \。txt'變成:匹配任何以字符\或」分隔的字符串「,其長度至少爲一個字符並以.txt結尾。 – user3180957

1

試試這個:

while (<DATA>) { 
    if(m/([^\\]+\.txt)"/) { 
     print "$1\n"; 
    } 
} 

__END__ 
val1-2.txt 
val2-3.txt 
val3-1.txt 

您不需要捕獲組以外的\。相反,尋找所有不是反斜槓而不是一切的東西。既然你想讓文件在.txt前面有一個名字,你希望+量詞,而不是*?這是匹配什麼或什麼都沒有,但得到儘可能少的

相關問題