2014-10-07 115 views
-1

我有以下perl代碼。我試圖grep從數組鏈接的路徑,並在末尾附加「\」或「/」,並將其推入新的數組。但我沒有得到期望的輸出。我錯過了什麼?PERL正則表達式並追加

use strict; 

my @links = (
    "incl -s projectA /. /abc/cde/efg", 
    "incl -s projectA \. \hij\klm\nop", 
); 

my ($path, $link, @linkpaths, $op); 
my $substr = "/"; 

foreach $link (@links) { 
    $link =~ m{incl -s projectA /. /|\\.\\(.+)}; 
    $path = $1; 
    print "Path is $path \n"; 
    if (index($path, $substr) != -1) { 
     print "$link contains $substr\n"; 
     $op = "/"; 
    } else { 
     print "$link doesnt contains $substr\n"; 
     $op = "\\"; 
    } 
    push @linkpaths, $path . $op; 
} 

print "\nlinkpaths:\n"; 
foreach (@linkpaths) { 
    print "$_\n"; 
} 

所需的輸出:

Path is abc/cde/efg 
abc/cde/efg contains/
Path is \hij\klm\nop 
hij\klm\nop doesnt contain/

linkpaths: 
abc/cde/efg/ 
hij\klm\nop\ 
+2

您應經常檢查匹配您使用捕捉變量之前'如果($鏈接= - M { } g){...}' – sln 2014-10-07 15:48:44

回答

2

的問題是,在你的字符串中的特殊字符 - 無論是簡單的字符串和正則表達式 - 沒有逃出來了,你有沒有use warnings在程序的頂部,這將有提醒你這個。

舉例來說,如果我添加use warnings,用Data::Dump顯示您的@links陣列我得到這個

Unrecognized escape \h passed through at E:\Perl\source\dd.pl line 8. 
Unrecognized escape \k passed through at E:\Perl\source\dd.pl line 8. 
[ 
    "incl -s projectA /. /abc/cde/efg", 
    "incl -s projectA . hijklm\nop", 
] 

所以一些在第二個元素反斜槓已經消失。

現在正則表達式看起來它的面前很好,但我希望這是明確的,你的交替延伸到圖案的全長,所以

m{incl -s projectA /. /|\\.\\(.+)} 

比賽要麼

incl -s projectA /./

\\.\\(.+) 

這完全不符合你的想法。您還需要避開.這些點,否則匹配換行符以外的任何字符;並且您已經放棄了空間,所以您目前有/. /(有中間空間)或\.\(沒有一個)。

這是一個有點棘手的問題,因爲(我認爲)你想在projectA之後捕獲所有內容,但也允許向前或向後斜線。這將成爲

m{incl -s projectA ((?:/\. /|\\\. \\).+)} 

其中,採用/x修改,並與\s+替換文字的空間,我希望你會同意可以更清楚地寫

m{ incl \s+ -s \s+ projectA \s+ ((?: /\. \s+/| \\\. \s+ \\) .+) }x 

這是你的代碼的固定版本,其中包括我所描述的所有更改。

use strict; 
use warnings; 

my @links = (
    'incl -s projectA /. /abc/cde/efg', 
    'incl -s projectA \. \hij\klm\nop', 
); 

my ($path, $link, @linkpaths, $op); 
my $substr = "/"; 

for my $link (@links) { 

    $link =~ m{incl \s+ -s \s+ projectA \s+ ((?: /\. \s+/| \\\. \s+ \\) .+)}x; 
    $path = $1; 
    print "Path is $path \n"; 
    if (index($path, $substr) >= 0) { 
     print "$link contains $substr\n"; 
     $op = "/"; 
    } 
    else { 
     print "$link doesn't contain $substr\n"; 
     $op = "\\"; 
    } 
    push @linkpaths, "$path$op"; 
} 


print "\n"; 
print "linkpaths:\n"; 
print "$_\n" for @linkpaths; 

輸出

Path is /. /abc/cde/efg 
incl -s projectA /. /abc/cde/efg contains/
Path is \. \hij\klm\nop 
incl -s projectA \. \hij\klm\nop doesn't contain/

linkpaths: 
/. /abc/cde/efg/ 
\. \hij\klm\nop\ 

更新

只捕捉最後路徑以斜槓或反斜槓開始輸入列表中的每個元素,我會用這個替換模式的結尾改爲。但我認爲使用角色類來代表向前或向後的斜線比如[/\\]更爲合適。

這是另一個改變你的整個程序

use strict; 
use warnings; 

my @links =(
    'incl -s projectA /. /abc/cde/efg', 
    'incl -s projectA \. \hij\klm\nop', 
); 

my @linkpaths; 
my $substr = '/'; 

for (@links) { 

next unless my ($path) = m{ incl \s+ -s \s+ projectA \s+ [/\\]\. \s+ ([/\\].+) }x; 

print "Path is $path\n"; 

my $op; 
if ($path =~ /\Q$substr/) { 
    printf "%s contains %s\n", $_, $substr; 
    $op = '/'; 
} 
else { 
    printf "%s doesn't contain %s\n", $_, $substr; 
    $op = '\\'; 
} 

push @linkpaths, "$path$op"; 
} 


print "\n"; 
print "linkpaths:\n"; 
print "$_\n" for @linkpaths; 

輸出

Path is /abc/cde/efg 
incl -s projectA /. /abc/cde/efg contains/
Path is \hij\klm\nop 
incl -s projectA \. \hij\klm\nop doesn't contain/

linkpaths: 
/abc/cde/efg/ 
\hij\klm\nop\ 
+0

如何讓我的正則表達式將路徑中的vaue設置爲'abc/cde/efg /'而不是'/。/ABC/CDE/efg'。請檢查我想要的輸出 – Jill448 2014-10-07 16:03:56

+0

@ sravs448:我已經添加到我的解決方案來解釋 – Borodin 2014-10-07 16:15:00

0

可能需要一個正則表達式這樣

# m{incl[ ]-s[ ]projectA(?|[ ]/\.[ ](/)|[ ]\\\.[ ](\\))((?:(?!\1$).)+)$}g 

incl [ ] -s [ ] projectA 
(?| 
     [ ] /\. [ ] 
     (/)       # (1) 
    | [ ] \\\. [ ] 
     (\\)      # (1) 
) 
(       # (2 start) 
     (?: 
      (?! \1 $) 
      . 
    )+ 
)        # (2 end) 
$ 

樣品:

use strict; 
use warnings; 

my @links =(
     'incl -s projectA /. /abc/cde/efg', 
     'incl -s projectA \. \hij\klm\nop' 
     ); 

my ($path,$link,@linkpaths,$op); 
my $substr="/"; 

for (@links) { 
    if (m{incl[ ]-s[ ]projectA(?|[ ]/\.[ ](/)|[ ]\\\.[ ](\\))((?:(?!\1$).)+)$}g) 
    { 
     ($op, $path) = ($1,$2); 
     print "Path is $path \n"; 
     if ($op eq '/') { 
      print "$path contains /\n"; 
     } 
     else { 
      print "$path doesnt contain /\n"; 
     } 
     push @linkpaths, $path . $op; 
    } 
} 
print "\nlinkpaths:\n"; 
for (@linkpaths) { 
    print "$_\n"; 
} 

輸出:

Path is abc/cde/efg 
abc/cde/efg contains/
Path is hij\klm\nop 
hij\klm\nop doesnt contain/

linkpaths: 
abc/cde/efg/ 
hij\klm\nop\