問:如何寫正則表達式,去只匹配固定位置的字符串?如匹配形如123abc789中的第四到第六位的字符,即只匹配其中的abc?
答:
解法一:.{3}abc
說明:先匹配任意3個字符,然后后面跟abc字符的字符串。
下圖可見,確實匹配到了字符abc, 但也匹配到之前的字符123,同時還匹配到了多個地方如defabc和456abc,即多次匹配。故不滿足問題要求。
分析:這里abc被匹配的位置可以到處亂竄。

解法二:^.{3}abc
說明:基於解法一的教訓,很容易想到正則中限定字符開始的語法^,讓其開頭必須滿足條件,這樣只能匹配一次。 匹配開頭任意3個字符,然后后面跟abc字符的字符串。
下圖可見,確實匹配到了第四到第六位的字符abc, 但也匹配到之前的字符123。故不滿足問題要求。

解法三:(?<=^.{3})abc
說明:基於解法一的弊端——多次匹配,且每次匹配內容超過指定寬度;基於解法二的弊端——一次匹配,且此次匹配內容超過指定寬度。
如果能讓真正要匹配的abc前面的內容不作為最終匹配結果,那不就可以了嗎?
零寬斷言!
exp1(?=exp2)exp3
exp1(?<=exp2)exp3
exp1(?!exp2)exp3
exp1(?<!exp2)exp3
以上(?)內的表達式exp2都不會作為最終匹配結果返回,只是作為判斷條件。
匹配開頭任意3個字符,以此作為判斷條件即斷言,而開頭的任意3個字符,又不作為最后匹配的實際寬度即零寬。然后后面跟abc字符的字符串,最后只匹配abc字符串即可。
補充說明:解法二中的^以及$或\b等都是正則的斷言元字符。但他們都不是零寬,所以導致可以限定匹配的結果只有一次,但匹配內容超過寬度。解法三正好是斷言元字符和零寬斷言的結合。

如果你有更好的解決方案或者發現文中有不足之處,歡迎留言評論。^_^
2021.07.09
Russell
