我需要用正则表达式匹配一个 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?))*'/
上面的正则表达式基于StringLiteral2011 年 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的东西',并且不会匹配特殊的\nand\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 控制台中测试。使用或不使用转义字符。