[英]How to combine two regular expressions into one with different $1?
[英]How do I combine these two regular expressions into one?
我正在使用 JavaScript 中的正則表達式編寫一個基本的詞法分析器,我有兩個正則表達式(一個用於單引號字符串,一個用於雙引號字符串),我希望將它們合並為一個。 這是我的兩個正則表達式(我添加了^
和$
字符以進行測試):
var singleQuotedString = /^'(?:[^'\\]|\\'|\\\\|\\\/|\\b|\\f|\\n|\\r|\\t|\\u[0-9A-F]{4})*'$/gi;
var doubleQuotedString = /^"(?:[^"\\]|\\"|\\\\|\\\/|\\b|\\f|\\n|\\r|\\t|\\u[0-9A-F]{4})*"$/gi;
現在我嘗試將它們組合成一個正則表達式,如下所示:
var string = /^(["'])(?:[^\1\\]|\\\1|\\\\|\\\/|\\b|\\f|\\n|\\r|\\t|\\u[0-9A-F]{4})*\1$/gi;
但是,當我測試輸入"Hello"World!"
它返回true
而不是false
:
alert(string.test('"Hello"World!"')); //should return false as a double quoted string must escape double quote characters
我認為問題出在[^\\1\\\\]
,它應該匹配除匹配組\\1
(它是單引號或雙引號 - 字符串的分隔符)和\\\\
(這是反斜杠字符)之外的任何字符)。
正則表達式正確過濾掉反斜杠並匹配分隔符,但它不會過濾掉字符串中的分隔符。 任何幫助將不勝感激。 請注意,我參考了 Crockford 的鐵路圖來編寫正則表達式。
你不能在字符類中引用匹配的組: (['"])[^\\1\\\\]
。試試這樣的:
(['"])((?!\1|\\).|\\[bnfrt]|\\u[a-fA-F\d]{4}|\\\1)*\1
(你需要添加更多的轉義,但你明白我的意思......)
快速解釋:
(['"]) # match a single or double quote and store it in group 1
( # start group 2
(?!\1|\\). # if group 1 or a backslash isn't ahead, match any non-line break char
| # OR
\\[bnfrt] # match an escape sequence
| # OR
\\u[a-fA-F\d]{4} # match a Unicode escape
| # OR
\\\1 # match an escaped quote
)* # close group 2 and repeat it zero or more times
\1 # match whatever group 1 matched
這也應該有效(原始正則表達式)。
如果速度是一個因素,這就是“展開”方法,據說是這種事情最快的方法。
(['"])(?:(?!\\|\1).)*(?:\\(?:[\/bfnrt]|u[0-9A-F]{4}|\1)(?:(?!\\|\1).)*)*/1
展開
(['"]) # Capture a quote
(?:
(?!\\|\1). # As many non-escape and non-quote chars as possible
)*
(?:
\\ # escape plus,
(?:
[\/bfnrt] # /,b,f,n,r,t or u[a-9A-f]{4} or captured quote
| u[0-9A-F]{4}
| \1
)
(?:
(?!\\|\1). # As many non-escape and non-quote chars as possible
)*
)*
/1 # Captured quote
好吧,您總是可以通過在較小的正則表達式上使用交替運算符來創建更大的正則表達式
/(?:single-quoted-regex)|(?:double-quoted-regex)/
或明確:
var string = /(?:^'(?:[^'\\]|\\'|\\\\|\\\/|\\b|\\f|\\n|\\r|\\t|\\u[0-9A-F]{4})*'$)|(?:^"(?:[^"\\]|\\"|\\\\|\\\/|\\b|\\f|\\n|\\r|\\t|\\u[0-9A-F]{4})*"$)/gi;
最后,如果您想避免代碼重復,您可以使用new Regex
構造函數動態構建此正則new Regex
。
var quoted_string = function(delimiter){
return ('^' + delimiter + '(?:[^' + delimiter + '\\]|\\' + delimiter + '|\\\\|\\\/|\\b|\\f|\\n|\\r|\\t|\\u[0-9A-F]{4})*' + delimiter + '$').replace(/\\/g, '\\\\');
//in the general case you could consider using a regex excaping function to avoid backslash hell.
};
var string = new RegExp( '(?:' + quoted_string("'") + ')|(?:' + quoted_string('"') + ')' , 'gi' );
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.