2017-05-19 70 views
0

我正在修改舊的郵件工具並添加MIME支持。我有很多工作,但我是一個perl虛擬和正則表達式的東西正在失去我。搜索子字符串並將該字符串的另一部分作爲變量存儲在perl中

我:

foreach (@{$body}) { 

    next if /^$/; 

    if (/NEMS/i) { 
     /.*?(\d{5,7}).*/; 
     $nems = $1; 
     next; 
    } 

    if ($delimit) { 
     next if (/$delimit/ && ! $tp); 
     last if (/$delimit/ && $tp); 

     $tp = 1, next if /text.plain/; 
     $tp = 0, next if /text.html/; 
     s/<[^>]*>//g; 
     $newbody .= $_ if $tp; 
    } else { 
     s/<[^>]*>//g; 
     $newbody .= $_ ; 
    } 
} # End Foreach 

現在我有$body_text作爲純文本郵件正文感謝MIME::Parser。所以,現在我只需要這部分工作:

foreach (@{$body_text}) { 

    next if /^$/; 

    if (/NEMS/i) { 
     /.*?(\d{5,7}).*/; 
     $nems = $1; 
     next; 
    } 
} # End Foreach 

的實際挑戰是找到NEMS=12345NEMS=1234567並設置$nems=12345如果找到。我認爲我在測試中遇到了一個非常基本的語法問題,因爲我並沒有經常接觸perl。

一個同事建議:

foreach (split(/\n/,$body_text)){ 

    next if /^$/; 

    if (/NEMS/i) { 
     /.*?(\d{5,7}).*/; 

     $nems = $1; 
next; 

    } 
} 

這似乎是工作,但它可能不會是首選的方法是什麼?

編輯:

因此,這是一個基於位置的提示和測試的最新版本:

foreach (split(/\n/,$body_text)){ 

    next if /^$/; 

    if (/NEMS/i) { 
     /^\s*NEMS\s*=\s*(\d+)/i; 

     $nems = $1; 
    next; 

    } 
} 
+0

還能有另一個數字 - 可以有八位數嗎?或者可能嚴格遵循非數字? – zdim

+0

至於「_A同事建議_」 - 如果'$ body_text'是一個普通的字符串,他們的建議是正確的,但如果它是對數組的引用(「_arrayref_」),則應該使用原始字符串。這些是非常不同的。 – zdim

+0

使用舊的Mail perl模塊的「舊」代碼是一個數組。在新的MIME中,它不是一個數組。 - 謝謝 –

回答

-1

比賽的最後兩位數字爲可選,並捕獲的第一個五年,並直接分配捕獲

($nems) = /.*? (\d{5}) (?: \d{2})?/x; # /x allows spaces inside 

構造(?:)只有組裏面沒有捕獲。它表示匹配零或一次後的?。我們需要parens,以便它只適用於該子模式。所以最後兩位數是可選的 - 五位數或七位數匹配。最後,我還刪除了不需要的.*

不過,你說的話看來,整個事情可以簡化

if (($nems) = /^\s*NEMS \s* = \s* (\d{5}) (?:\d{2})?/ix) { next } 

那裏現在有沒有必要if (/NEMS/),我已經調整到澄清NEMS是在開始和=附近可能有空格。然後,你也可以說

my $nems; 

foreach (split /\n/, $body_text) { 
    # ... 
    next if ($nems) = /^\s*NEMS\s*=\s*(\d{5})(?:\d{2})?/i; 
    # ... 
} 

什麼包括澄清新$body_text是一個多字符串。

很明顯,$nems宣佈(需要)以外的循環,我指出。

這允許更多數字跟隨;它也將匹配8位數字(但只捕獲前五個數字)。這是正則表達式中尾隨.*的含義。

編輯  已經說明只能有5或7位數字。然後,可以收緊正則表達式,檢查輸入是否如預期的那樣,但它也應該像現在這樣工作。


的幾個注意事項,讓我知道,如果有更多的將是有益的

  • 匹配操作符返回一個列表,所以我們需要($nems) = /.../;

  • 的括號的($nems) = /.../語法一個不錯的快捷方式,($nems) = $_ =~ /.../;
    如果你在$_以外的變量上匹配,那麼你需要整個事情。

  • 總是希望與

    ​​

    這直接幫助也能得到更好的代碼開始Perl程序。


理解狀態演進問題,即所有的數字下面=需要被捕獲到$nems(也有可能是5,(未6),7,8,9,10個數字)的澄清。然後在正則表達式僅僅是

($nems) = /^\s*NEMS\s*=\s*(\d+)/i; 

其中\d+意味着一個數字,一次或多次。所以一串數字(如果沒有的話匹配失敗)。

+0

@MarkM我首先誤解了部分問題。調整我認爲你需要的答案。 – zdim

+0

我在這個問題中增加了一個同事建議。評論歡迎。最初的假設是資產ID標籤始終爲5位或7位。我們指定電子郵件請求主體可以使用資產ID來幫助將票分配給正確的資產。 NEMS = xxxxx或NEMS = xxxxx是兩種可能的模式,並且NEMS將始終在行的開頭,而行中沒有其他任何內容。 $ nems稍後用於查找數據庫中的資產。 –

+0

@MarkM我已更新到這些說明。這些是「正常的」正則表達式調整,抱歉,我沒有放在所有的空間等等。至於同事的建議,請參閱我的問題下面的問題:這將表明'$ body_text'只是一個多行字符串,什麼是與你說的'$ body'(是一個arrayref)成功處理的內容非常不同。你可以通過'print'來查看$ body_text \ n「' - 如果它打印出ARRAY(...)',那麼原始版本是正確的('@ $ body_text'),如果它打印整個東西,則更改爲新的一個。這隻會改變'foreach'的路線。 – zdim

相關問題