我需要用正则表达式匹配一个 javascript 字符串,这是一个用单引号括起来的字符串,并且只能包含一个反斜杠单引号。
我将匹配的示例字符串如下所示:
'abcdefg'
'abc\'defg'
'abc\'de\'fg'
我需要用正则表达式匹配一个 javascript 字符串,这是一个用单引号括起来的字符串,并且只能包含一个反斜杠单引号。
我将匹配的示例字符串如下所示:
'abcdefg'
'abc\'defg'
'abc\'de\'fg'
这是匹配所有有效 JavaScript 文字字符串(由单引号包围'
)并拒绝所有无效字符串的正则表达式。请注意,假定为严格模式。
/'(?:[^'\\\n\r\u2028\u2029]|\\(?:['"\\bfnrtv]|[^\n\r\u2028\u2029'"\\bfnrtvxu0-9]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})|\\(?:\n|\r\n|\r(?!\n)|[\u2028\u2029]))*'/
或更短的版本:
/'(?:[^'\\\n\r\u2028\u2029]|\\(?:[^\n\rxu0-9]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|\n|\r\n?))*'/
上面的正则表达式基于StringLiteral
2011 年 6 月发布的 ECMAScript 语言规范 5.1 版中指定的(忽略双引号版本)的定义。
用双引号括起来的 JavaScript 文字字符串的正则表达式"
几乎相同:
/"(?:[^"\\\n\r\u2028\u2029]|\\(?:[^\n\rxu0-9]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4}|\n|\r\n?))*"/
让我们剖析一下这个怪物(更长的版本,因为它是从语法直接翻译而来的):
A StringLiteral
(忽略双引号版本)以 开头和结尾'
,如在正则表达式中所示。在引号之间是一个可选的SingleStringCharacter
. 这解释了*
- 0 个或更多字符。
SingleStringCharacter
定义为:
单字符串字符 :: SourceCharacter 但不是 ' 或 \ 或 LineTerminator 之一 \ 转义序列 行继续
[^'\\\n\r\u2028\u2029]
对应第一条规则
\\(?:['"\\bfnrtv]|[^\n\r\u2028\u2029'"\\bfnrtvxu0-9]|0(?![0-9])|x[0-9a-fA-F]{2}|u[0-9a-fA-F]{4})
对应第二条规则
\\(?:\n|\r\n|\r(?!\n)|[\u2028\u2029])
对应第三条规则
让我们看看第一条规则:SourceCharacter but not one of ' or \ or LineTerminator
. 第一条规则处理“正常”字符。
SourceCharacter
是任何 Unicode 单位。
LineTerminator
是换行符<LF>
(\u000A
或\n
)、回车符<CR>
(\u000D
或\r
)、行分隔符<LS>
( \u2028
) 或段落分隔符<PS>
( \u2029
)。
所以我们将只使用一个否定字符类来表示这个规则:[^'\\\n\r\u2028\u2029]
.
对于处理转义序列的第二条规则,您可以看到\
before EscapeSequence
,因为它出现在正则表达式中。至于EscapeSequence
,这是它的语法(严格模式):
转义序列:: 字符转义序列 0 [前瞻∉ DecimalDigit] 十六进制转义序列 Unicode转义序列
['"\\bfnrtv]|[^\n\r\u2028\u2029'"\\bfnrtvxu0-9]
是 的正则表达式CharacterEscapeSequence
。它实际上可以简化为[^\n\r\u2028\u2029xu0-9]
第一部分是SingleEscapeCharacter
, 包括'
, "
, \
, 和用于控制字符b
, f
, n
, r
, t
, v
.
第二部分是NonEscapeCharacter
,也就是SourceCharacter but not one of EscapeCharacter or LineTerminator
。EscapeCharacter
定义为SingleEscapeCharacter
,DecimalDigit
或 x
(对于十六进制转义序列)或u
(对于 unicode 转义序列)。
0(?![0-9])
是第二条规则的正则表达式EscapeSequence
。这是为了指定空字符\0
。
x[0-9a-fA-F]{2}
是正则表达式HexEscapeSequence
u[0-9a-fA-F]{4}
是正则表达式UnicodeEscapeSequence
第三条规则处理跨越多行的字符串。我们来看看LineContinuation
和其他相关的语法:
LineContinuation ::
\ LineTerminatorSequence
LineTerminatorSequence ::
<LF>
<CR> [lookahead ∉ <LF> ]
<LS>
<PS>
<CR> <LF>
\\(?:\n|\r\n|\r(?!\n)|[\u2028\u2029])
对应上面的语法。
没那么难……
此外,您需要检测一些其他可能的字符序列,例如\n
,\r
或\\
,在 javascript 中没有转义的换行是无效的,您必须使用该\n
序列。
/^'([^\\'\n\r]|\\'|\\n|\\r|\\\\)*'$/
执行中:
var sample = ["'abcdefg'", // Valid
"'abc\\'defg'", // Valid
"'abc\\'de\\'fg'", // Valid
"'abc\\'\\r\\nde\\'fg'", // Valid
"'abc\\'\r\nde\\'fg'", // Invalid
"'abc'def'" // Invalid
];
for(var i = 0; i < sample.length; i++)
console.log(sample[i].match( /^'([^\\'\n\r]|\\'|\\n|\\r|\\\\)*'$/ ));
^
告诉匹配器下一个条件必须匹配字符串的开头'
将匹配'
分隔符(
打开一个群组[^\\'\n\r]
匹配任何不同于\
and的东西'
,并且不会匹配特殊的\n
and\r
字符|
|
如果上述条件不匹配,将测试右侧\\'
将匹配\'
\\n
将匹配\n
文字字符串|\\r
或将匹配\r
文字字符串|\\\\
或将匹配\\
文字字符串)*
关闭组并允许它重复多次并允许它不存在(例如空字符串)'
将匹配最终'
分隔符$
告诉匹配器这必须是字符串的 and试试这个:
/'(?:[^'\\]|\\'|\\(?!'))*'/
在您的控制台中测试它:
/'(?:[^'\\]|\\'|\\(?!'))*'/.exec("'abc\\\'de\\\'fg'")
它会匹配
NOT ' or \
(除了)\'
(或者)\
(后面没有'
)如果您希望它匹配整个字符串,请使用字符串^
开头和字符串$
结尾标记:
/^'(?:[^'\\]|\\'|\\(?!'))*'$/
...这将匹配'string'
,'string\'s are awesome'
但不匹配'string's are awesome'
或'string's
尝试这个
/^'([az]*(?:\')?[az])+'$/
在此处查看示例
str = 'abc\'de\'fg';
match = str.match(/^([a-z\\']+)$/g);
在 Firebug 控制台中测试。使用或不使用转义字符。