2 回答

TA貢獻1847條經驗 獲得超11個贊
每個參數應該只匹配一次。
是主要問題。
對于您的示例,我提出了以下正則表達式:
/abcd\s*\((?!(?:'[^']*'|[^')])*(?<=[\s(,])(name|count|id)(?=[\s=])(?:'[^']*'|[^')])*(?<=[\s,])\1(?=[\s=]))(?:(?<=[(,])\s*(?:name\s*=\s*'(?<name>[^']*?)'|count\s*=\s*'(?<count>[^']*?)'|id\s*=\s*'(?<id>[^']*?)')\s*[,)]){3}(?<=\))
它很長,所以讓我們分解一下。
/<function?name>\s*\(...(?<=\))
匹配函數名稱function name
、開頭(
(+ 斷言正則表達式以結尾結束)
)、可選空格(我不會在正則表達式的其余部分討論)和/
名稱前的 a。請注意,java 不需要轉義/
.
(?!...)
這是檢查沒有參數被多次使用的部分。將...
被一個子正則表達式替換,如果相同的值被使用兩次,該子正則表達式將匹配。子正則表達式是完整正則表達式的分解形式,用于模擬匹配的名稱-值對。
(?:'[^']*'|[^')])*
匹配(盡可能多)既不是也不是'
結束符的任何字符,或者)
匹配一個由 分隔且不包含的值。這將有效地讀取空格、逗號、等號和 argnames 以及完整的值。'
'
(?<=[\s(,])(<argname1>|<argname2>|...)(?=[\s=])
匹配任何參數名稱argname<n>
。還要檢查它是一個完整的名稱,而不僅僅是一個子字符串。(
如果名稱前有空格、逗號或空缺,則這是一個完整的名稱。完整名稱后是空格或=
.?匹配的 argname 存儲在捕獲組 1 中。請注意,此子正則表達式(在 中)以匹配任何(?!...)
名稱的方式編寫。因此它將嘗試匹配所有 argnames 并僅在沒有(no = not any)argname 被使用兩次時才接受。
(?:'[^']*'|[^')])*
同上。匹配每個字符或完整值。
(?<=[\s,])\1(?=[\s=])
將第一個捕獲組(任何 argname)的內容重新匹配為完整名稱(名稱前的空格或逗號,=
名稱后的空格或逗號)。這是重要的部分。?這是第二次使用參數名稱的測試。
(?:(?<=[(,])\s*(?:...)\s*[,)]){<num?arguments>}
匹配num arguments
許多參數。每個參數必須以開頭(
(第一個)或逗號(除第一個以外的所有內容)開頭。此外,每個參數必須以逗號或結束符結尾)
。
包含...
參數規范和捕獲組的形式
<argname1>\s*=\s*'(?<argname1>[^']*)'|<argname2>\s*=\s*'(?<argname2>[^']*)'|...
其中 for 的值agname<n>
存儲在具有相同名稱的捕獲組中。Matcher
您可以使用 argname 作為組名從 java 中獲取該值。舉個例子matcher.group("count")
。

TA貢獻1836條經驗 獲得超5個贊
如果要將選項與它們之間的逗號匹配,可以在 id 的值之后更改()
for ,并為結束參數添加一個額外的子句,
此正則表達式(與您的略有不同)將匹配括號之間的任意數量的參數,以逗號和空格分隔
\/abcd\((id='[^']*', |name='[^']*', |count='[^']*', )*(id='[^']*'|name='[^']*'|count='[^']*')\)
您可以在這里試用regexr.com/4iqlu
編輯:將 .* 替換為 [^']*,因為我們要確保正則表達式不會在 '' 之外捕獲
添加回答
舉報