【发布时间】:2012-12-10 11:09:11
【问题描述】:
我需要用正则表达式匹配一个javascript字符串,这是一个用单引号括起来的字符串,并且只能包含一个反斜杠单引号。
我将匹配的示例字符串如下所示:
'abcdefg'
'abc\'defg'
'abc\'de\'fg'
【问题讨论】:
-
字符串是否可以包含除 alpha 字符和转义单引号以外的任何内容?
标签: javascript regex
我需要用正则表达式匹配一个javascript字符串,这是一个用单引号括起来的字符串,并且只能包含一个反斜杠单引号。
我将匹配的示例字符串如下所示:
'abcdefg'
'abc\'defg'
'abc\'de\'fg'
【问题讨论】:
标签: javascript regex
这是匹配所有有效 JavaScript 文字字符串(由单引号 ' 包围)并拒绝所有无效字符串的正则表达式。请注意,假定为 strict 模式。
/'(?:[^'\\\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?))*'/
上述正则表达式基于 2011 年 6 月发布的 ECMAScript 语言规范 5.1 版中指定的StringLiteral(忽略双引号版本)的定义。
用双引号 " 包围的 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?))*"/
让我们剖析一下怪物(较长的版本,因为它是从语法直接翻译而来的):
StringLiteral(忽略双引号版本)以 ' 开头和结尾,正如在正则表达式中所见。在引号之间是SingleStringCharacter 的可选序列。这解释了* - 0 个或更多字符。
SingleStringCharacter 定义为:
[^'\\\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]。
对于处理转义序列的第二条规则,您可以在EscapeSequence 之前看到\,因为它出现在正则表达式中。至于EscapeSequence,这是它的语法(严格模式):
['"\\bfnrtv]|[^\n\r\u2028\u2029'"\\bfnrtvxu0-9] 是CharacterEscapeSequence 的正则表达式。其实可以简化为[^\n\r\u2028\u2029xu0-9]
第一部分为SingleEscapeCharacter,包括'、"、\,以及用于控制字符的b、f、n、r、t、@ 987654364@.
第二部分是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])对应上面的语法。
【讨论】:
var str = ''' 或 var str = """ 但它们不应该...:/
var str = ''' 是允许的,因为你的两个正则表达式没有 ^ 和 $ 来指定开始和结束。所以,我认为这个“更好”:^"(?:[^"\\\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?))*"$|^'(?:[^'\\\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?))*'$ 它同时处理 '' 和 "" 字符串 :)
''' 不能被上面的正则表达式匹配。您可能会得到匹配,因为 '' 被视为匹配。添加或不添加锚点取决于您的用例。
试试这个:
/'(?:[^'\\]|\\'|\\(?!'))*'/
在您的控制台中测试它:
/'(?:[^'\\]|\\'|\\(?!'))*'/.exec("'abc\\\'de\\\'fg'")
会匹配
NOT ' or \(除外)\'(或)\(后面不跟')如果您希望它匹配整个字符串,请使用^ 字符串开头和$ 字符串结尾标记:
/^'(?:[^'\\]|\\'|\\(?!'))*'$/
... 将匹配 'string'、'string\'s are awesome' 但不匹配 'string's are awesome' 或 'string's
【讨论】:
*,所以它不会回溯,并且匹配一个空字符串。也改为非捕获组。干杯。
没那么难……
另外,您需要检测一些其他可能的字符序列,例如\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] 匹配与 \ 和 ' 不同的任何字符,并且不会匹配特殊的 \n 和 \r 字符| 如果上面的条件不匹配,则测试| 的右侧\\' 将匹配 \'
\\n 将匹配 \n 文字字符串|\\r 或将匹配 \r 文字字符串|\\\\ 或将匹配 \\ 文字字符串)*关闭组并允许它重复多次并允许它不存在(例如空字符串)' 将匹配最后的 ' 分隔符$ 告诉匹配器这必须是字符串的 and 【讨论】:
^和$,现在坏阵型不匹配了
[^\\'] 之后的* 可以被移除以减少回溯。
[^\\']* 会导致性能问题,因为它会匹配每个字符直到' 或\ 字符,所以在字符串'12345' [^\\']* 将匹配5连续的字符(5 个滴答声),而不是失败(1 个滴答声)并处理 \\',这也将失败(1 个滴答声)并留下大约 7 个滴答声。如果* 不存在,它将匹配 1 个字符(1 个刻度)处理组(1 个刻度)匹配其他字符并执行 5 次以使组离开大约 12 个刻度
试试这个
/^'([a-z]*(?:\')?[a-z])+'$/
参见示例here
str = 'abc\'de\'fg';
match = str.match(/^([a-z\\']+)$/g);
在 Firebug 控制台中测试。使用或不使用转义字符。
【讨论】:
javascript和regex?
null。 JavaScript 正则表达式的符号与其他语言的正则表达式略有不同。
[a-z]?另外,这个正则表达式允许var str = '''
var str = ''' 不是有效字符串,除非您转义中间引号。