2013-08-29 134 views
0

我試圖用正則表達式從分號分隔的字符串中刪除令牌。一個例子字符串如下所示:Perl正則表達式替換問題

Field1=Blah;Field2=Bluh;Field3=Dingdong;Uid=John;Pwd=secret;Field4=lalali Field1=Blah;Field2=Bluh;Field3=Dingdong;Uid=John;Pwd=secret;Field4=lalali;

所以我想刪除「UID」和「密碼」,在單獨的命令令牌,如不刪除任何尾隨令牌(如字段4應保持在結束)。

我現在的嘗試是要做到:

$mystring =~s /Uid=.+;//i;

這將產生

Field1=Blah;Field2=Bluh;Field3=Dingdong;Field4=lalali

這對於第一線工作,但不會用分號二號線工作最後,它在哪裏產生

Field1=Blah;Field2=Bluh;Field3=Dingdong;

並錯誤地刪除Field4。我嘗試了許多變化,像

$mystring =~s /Uid=.+;?//i; $mystring =~s /Uid=.+;+?//i;

沒有成功。我意識到我需要告訴正則表達式只匹配第一個分號,但我不知道如何。

現在,只要讓我不看完全傻了,我能得到它這樣做的工作:

$mystring =~s /Uid=[^;]+;//i;

,但我仍然不知道爲什麼我不能告訴表達式只匹配到第一個分號...

回答

4

當你使用一個量詞如+*,那麼他們是貪婪的。他們吞噬儘可能多的角色,只有當他們被迫回溯時纔會讓他們回來。模式.*;因此將匹配所有內容,直到最後一個分號。

也許貪婪的量詞應該減肥。我們可以通過使用懶惰版本強制他們:+?*?。這些將盡快終止。因此,這個模式將是:

/Uid=.+?;/ # repeat for Pwd 

相匹配,直到第一分號

這工作,但它被認爲是良好的風格,而使用一個否定的字符類代替非貪婪量詞與.類別:

/Uid=[^;]+;/ 

因爲這樣做可能會出錯的方式較少(如刪除該行的其餘部分)。它也比其他解決方案更明確。

+0

咦?我有什麼問題嗎?請尊敬downvoter,啓發我...(這不是我需要的代表,我想了解這個答案可能會更有用) – amon

3

如果你不想使用否定字符類(這將適用於大多數正則表達式包),你可以使用非貪婪量詞匹配數據遵循關鍵字(但它只能與Perl兼容的正則表達式包一起使用)。有關更多信息,請參見Regular expressions下的量詞。

$mystring =~s /Uid=.+?;//i; 

額外的問號使得+非貪心;它取最小字符串匹配而不是最大值,所以它不會匹配任何分號。