1

我需要用正则表达式匹配一个 javascript 字符串,这是一个用单引号括起来的字符串,并且只能包含一个反斜杠单引号。

我将匹配的示例字符串如下所示:

'abcdefg'
'abc\'defg'
'abc\'de\'fg'
4

4 回答 4

2

这是匹配所有有效 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 LineTerminatorEscapeCharacter定义为SingleEscapeCharacter,DecimalDigitx(对于十六进制转义序列)或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])对应上面的语法。

于 2012-12-10T11:29:10.947 回答
0

没那么难……

此外,您需要检测一些其他可能的字符序列,例如\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|\\\\)*'$/ ));
  1. ^告诉匹配器下一个条件必须匹配字符串的开头
  2. '将匹配'分隔符
  3. (打开一个群组
  4. [^\\'\n\r]匹配任何不同于\and的东西',并且不会匹配特殊的\nand\r字符
  5. ||如果上述条件不匹配,将测试右侧
  6. \\'将匹配\'
  7. \\n将匹配\n文字字符串
  8. |\\r或将匹配\r文字字符串
  9. |\\\\或将匹配\\文字字符串
  10. )*关闭组并允许它重复多次并允许它不存在(例如空字符串)
  11. '将匹配最终'分隔符
  12. $告诉匹配器这必须是字符串的 and
于 2012-12-10T11:33:42.833 回答
0

试试这个:

/'(?:[^'\\]|\\'|\\(?!'))*'/

在您的控制台中测试它:

/'(?:[^'\\]|\\'|\\(?!'))*'/.exec("'abc\\\'de\\\'fg'")

它会匹配

  • 任意数量的字符:
    • NOT ' or \(除了)
    • \'(或者)
    • \(后面没有'

如果您希望它匹配整个字符串,请使用字符串^开头和字符串$结尾标记:

/^'(?:[^'\\]|\\'|\\(?!'))*'$/

...这将匹配'string''string\'s are awesome'但不匹配'string's are awesome''string's

于 2012-12-10T11:26:49.460 回答
-2

尝试这个

/^'([az]*(?:\')?[az])+'$/

在此处查看示例

str = 'abc\'de\'fg';

match = str.match(/^([a-z\\']+)$/g);

在 Firebug 控制台中测试。使用或不使用转义字符。

于 2012-12-10T11:27:26.547 回答