2012-04-18 132 views
4

我正在读取格式化字符串中的信息。 格式如下:“:”我想用正则表达式来提取数据是正则表达式来解析带有转义字符的字符串

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

之间的一切。如果a:后跟另一个:(如“::”),则其数据必须为“”(一个空字符串)。

目前我与此正则表达式解析它:

(.*?)(:|$) 

现在它来到了我的脑海里“:”可以在数据中存在,也是如此。所以它必须逃脱。 例子:

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

我怎样才能改变我的正则表达式,以便它匹配的“\:”作为数据吗?

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

感谢, 麦克法兰

回答

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 
+0

我收到这个输出: [“foo”,“”,“bar”,“”,“beer”,“”,“”:“,”“,”“,”1337“,”“] – McFarlane 2012-04-18 12:22:28

+0

啊, 对。 RegexBuddy“足够聪明”以省略多余的空匹配,JavaScript和Python(我现在正在测试它)不是。让我们看看我能否找到解决方案。 – 2012-04-18 12:26:10

+0

您更新的示例与预期的数据相匹配,但它会一直返回[“”,“”]。在你的例子中,循环会导致无限循环,因为匹配永远不会为空。我限制了while循环来做[subject.match(myregexp).length-1]迭代。不过,我会将您的答案标记为正确,因为正则表达式很棒。非常感谢您的努力。 – McFarlane 2012-04-18 12:56:41

2

使用负向后断言。

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

,如果它不通过前面\这将只匹配:

+0

它在我的正则表达式测试中工作,但它在我的代码中不起作用。我正在使用JavaScript作为编程语言。它似乎有一些限制,虽然我找不到任何页面来定义它们。 – McFarlane 2012-04-18 12:03:28

+3

JavaScript不支持lookbehind断言。 – 2012-04-18 12:10:23

+0

好,那就用''[([^ \\]:| $)'' – 2012-04-18 12:21:45

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,这应该给这些令牌的示例:\ab\n<empty string>\:x

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

在试图更清晰:字符串放到标记生成器将被解释,它有2个特殊字符:\:

  • \只会有只有其次是具有特殊意义\:,并且将有效地“逃离”这些字符:这意味着它们将失去它们对于标记器的特殊含义,并且它们将被视为任何正常字符(并且因此将成为标记的一部分)。
  • :是分隔2个标记的标记。

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

相关问题