2012-04-18 131 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沒有要求斜線轉義,但其他觀衆可能需要一個完整的解析庫,允許數據中的任何字符。

相關問題