你似乎誤解如何該正則表達式的作品。讓我打破它給你:
(?= lookahead assertion: the following pattern must match, but
will not consume any of the text.
(.{3})* matches a series of 3 characters, any number of times. In
other words, this consumes characters in multiples of 3.
(.{4})$ makes sure there are exactly 4 characters left.
)
這種模式在要插入一個破折號-
每一個地方產生空匹配。這就是爲什麼preg_replace("/(?=(.{3})*(.{4})$)/", "-", "1231231234");
在正確的位置插入破折號 - 替換空字符串與插入相同。讓我們來看看這一步一步,使用文本31231234
爲例:
remaining text remaining pattern what happens
step 0: 31231234 (.{3})*(.{4})$ (.{3})* matches one time
step 1: 31234 (.{3})*(.{4})$ (.{3})* matches again
step 2: 34 (.{3})*(.{4})$ (.{3})* fails to match another time
step 3: 34 (.{4})$ (.{4}) fails to match -> backtrack
step 5: 31234 (.{4})$ (.{4}) fails to match -> pattern failed to
match, no dash will be inserted.
後的格局未能在位置0中的文本匹配,將再次在位置1檢查(剩餘的文本是1231234
):
remaining text remaining pattern what happens
step 0: 1231234 (.{3})*(.{4})$ (.{3})* matches one time
step 1: 1234 (.{3})*(.{4})$ (.{3})* matches again
step 2: 4 (.{3})*(.{4})$ (.{3})* fails to match another time
step 3: 4 (.{4})$ (.{4})$ matches -> dash will be inserted
here, giving "3-1231234"
同樣的事情再次發生3個字符後,讓最終的結果3-123-1234
。換言之,組(.{4})$
指定在文本的最後4個字符中不應插入破折號。通過消耗最後4個字符,如果剩餘的字符數少於4個字符,則無法匹配模式。這就是爲什麼(.{4})(.{4})$
和(.{4}){2}$
都會產生8個字符的塊 - 如果少於8個字符,則該模式不能匹配。
爲了插入另一短跑在過去的8個字符,你必須使用4個字符.{4}
兩組,讓其中一人可選:
(?=((.{3})*.{4})?(.{4})$)
感謝您的詳細解釋。還有一個問題。當使用$時,它實際上是從這一點開始的回溯搜索,還是某種從左至右的重複?例如,在這個簡單的測試中:https://regex101.com/r/eE6zK7/1它表示該比賽是在20步後發現的。 – Rafael
@Rafael:'$'只是一個字符串末尾的錨,它不會影響正則表達式的「方向」。如果你點擊regex101上的「調試器」,你可以看到它是如何一步一步匹配的。 –