正则表达式解析带有转义字符的字符串

时间:2012-04-18 11:47:33

标签: javascript regex

我正在从格式化的字符串中读取信息。 格式如下:

"foo:bar:beer:123::lol"

“:”之间的所有内容都是我想用正则表达式提取的数据。如果a:后跟另一个:(如“::”),则该数据必须为“”(空字符串)。

目前我用这个正则表达式解析它:

(.*?)(:|$)

现在我想到了数据中也可能存在“:”。所以它必须被逃脱。 例如:

"foo:bar:beer:\::1337"

如何更改正则表达式以使其与“\:”匹配作为数据呢?

编辑:我使用JavaScript作为编程语言。它似乎对复杂的规则表达有一些限制。解决方案也应该在JavaScript中运行。

谢谢, 麦克法兰

3 个答案:

答案 0 :(得分:3)

var myregexp = /((?:\\.|[^\\:])*)(?::|$)/g;
var match = myregexp.exec(subject);
while (match != null) {
    for (var i = 0; i < match.length; i++) {
        // Add match[1] to the list of matches
    }
    match = myregexp.exec(subject);
}

输入:"foo:bar:beer:\\:::1337"

输出:["foo", "bar", "beer", "\\:", "", "1337", ""]

你总是得到一个空字符串作为最后一个匹配。这是不可避免的,因为要求您还希望空字符串在分隔符之间匹配(以及JavaScript中缺少lookbehind断言)。

<强>解释

(          # Match and capture:
 (?:       # Either match...
  \\.      # an escaped character
 |         # or
  [^\\:]   # any character except backslash or colon
 )*        # zero or more times
)          # End of capturing group
(?::|$)    # Match (but don't capture) a colon or end-of-string

答案 1 :(得分:2)

使用负面的lookbehind断言。

(.*?)((?<!\\):|$)

如果:之前的不是,则只会匹配\

答案 2 :(得分:1)

这是一个解决方案:

function tokenize(str) {
  var reg = /((\\.|[^\\:])*)/g;
  var array = [];
  while(reg.lastIndex < str.length) {
    match = reg.exec(str);
    array.push(match[0].replace(/\\(\\|:)/g, "$1"));
    reg.lastIndex++;
  }
  return array;
}

根据:字符将字符串拆分为令牌。

  • 但如果您希望:字符成为令牌的一部分,则可以将\字符转义为\
  • 如果您希望\成为令牌的一部分,则可以将\转义为\a
  • 不会解释任何其他\a。 (即:\a:b:\n::\\:\::x仍为\a
  • 因此,只要数据格式正确,您就可以在令牌中放置任何数据。

以下是字符串b的示例,该字符串应提供以下令牌:\n<empty string>\:,{{1} },x>>> tokenize("\\a:b:\\n::\\\\:\\::x"); ["\a", "b", "\n", "", "\", ":", "x"]

\

为了更清楚:放入标记器的字符串将被解释,它有2个特殊字符::\

  • \只有在::后面才会有特殊含义,并且会有效地“逃避”这些字符:这意味着它们将失去对tokenizer的特殊含义,并且它们将被视为任何正常角色(因此将成为令牌的一部分)。
  • {{1}}是分隔2个令牌的标记。

我意识到OP没有要求斜线转义,但其他观众可能需要一个完整的解析库来允许数据中的任何字符。