6

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

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

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

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

(.*?)(:|$)

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

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

如何更改我的正则表达式,使其也匹配“\:”作为数据?

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

谢谢,麦克法兰

4

3 回答 3

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 中缺少后向断言),这是不可避免的。

解释:

(          # 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
于 2012-04-18T12:15:16.637 回答
3

这是一个解决方案:

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;
}

它根据字符将字符串拆分为标记:

  • 但是,如果您希望它成为令牌的一部分,您可以转义:字符。\
  • 如果您希望它成为令牌的一部分,您可以逃避\with\
  • 任何其他\都不会被解释。(即:\a遗骸\a
  • 因此,只要事先正确格式化数据,您就可以将任何数据放入令牌中。

这是一个带有字符串的示例\a:b:\n::\\:\::x,它应该给出这些标记:\a, b, \n, <empty string>, \, :, x

>>> tokenize("\\a:b:\\n::\\\\:\\::x");
["\a", "b", "\n", "", "\", ":", "x"]

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

  • \只有在\or之后才具有特殊含义:,并且将有效地“转义”这些字符:这意味着它们将失去对标记器的特殊含义,并且它们将被视为任何普通字符(因此将成为标记的一部分)。
  • :是分隔 2 个标记的标记。

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

于 2013-11-19T14:03:44.890 回答
2

使用否定的lookbehind断言。

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

:仅当它前面没有.时才会匹配\

于 2012-04-18T11:50:31.807 回答