例如有一個需求如下:
tag格式為[quotePostId=XX]YY[/quotePostId],XX填數字,YY填文字,
可嵌套,如何從以下tag嵌套中找出最內層的XX和YY:
[tagId=1]kk[tagId=2][tagId=3]kk[/tagId]kk[/tagId][/tagId]
這裡提供一個解法,匹配的Group1即為XX、Group2為YY
\[tagId=(\d+)\](?=((?:[^\[]|\[(?!(?:tagId=\d+\]|\/tagId\])))*))\2\[\/tagId\]
下面來做解釋:
思路是:
- 必須符合[tagId=XX]YY[/tagId]。
- XX必須為非空值之數字。
- YY可為空值或任何字元。
- YY不可含有[tagId=??]或[/tagId],因為含有即代表此次匹配YY不為最內層tag之內容。
實作步驟(???為還未確定的部份,用紅色標色,當下確定的地方用藍色標色,之前確定的用黑色標色):
- 首先因為必須符合[tagId=XX]YY[/tagId],即XX必須為非空值之數字,所以先寫出一開始的正規表示法。
\[tagId=(\d+)\](???)\[\/tagId\] - 歩驟1的???需要符合條件(思路4)才須匹配,否則匹配不成功,因為x(?=y)這個語法不會把y算在匹配成功的字串內,所以用\2來裝Group2選到的YY放到tag中間。
\[tagId=(\d+)\](?=(???))\2\[\/tagId\] - YY可為空值,所以在Group2裡面放一個不記Group編號的Group,然後此Group可以0到多個。
\[tagId=(\d+)\](?=((?:???)*))\2\[\/tagId\] - 開始匹配YY,分成碰到非左中括弧( [ )、或是左中括弧的兩種情況。
當是左中括弧時,根據後面接的字串決定要不要匹配。
\[tagId=(\d+)\](?=((?:[^\[]|\[(???))*))\2\[\/tagId\] - 如是是左中括弧時,根據後面接的字串情況決定要不要匹配,不匹配的情況有兩種,
第一種:為[tagId=x]
\[tagId=(\d+)\](?=((?:[^\[]|\[(?!(?:tagId=\d+\]|???)))*))\2\[\/tagId\]
第二種:為[/tagId]
\[tagId=(\d+)\](?=((?:[^\[]|\[(?!(?:tagId=\d+\]|\/tagId\])))*))\2\[\/tagId\]
最後我們完成了正規表示法:
\[tagId=(\d+)\](?=((?:[^\[]|\[(?!(?:tagId=\d+\]|\/tagId\])))*))\2\[\/tagId\]
以下為可測試的線上工具: