2013-07-09 43 views
2

如果我有一個由字符分隔的字符串,讓我們這樣說:將字符串分割,同時保持分隔符,除了逃脫的人(正則表達式)

a-b-c 

,我想保留分隔符,我可以使用向後看和前瞻,以保持自己的分隔符,如:

string.split("((?<=-)|(?=-))"); 

導致

  • a
  • -
  • b
  • -
  • c

現在,如果分隔符的一個逃脫的是這樣的:

a-b\-c 

而且我希望遵守逃逸,我想出了使用這樣的正則表達式:

((?<=-(?!(?<=\\-))) | (?=-(?!(?<=\\-)))) 

ERGO現在

string.split("((?<=-(?!(?<=\\\\-)))|(?=-(?!(?<=\\\\-))))"): 

,這部作品並導致:

  • a
  • -
  • b\-c

(我後來用string.replace("\\", "");刪除的反斜槓,我還沒有找到一種方法將其包含在正則表達式中)

我的問題是理解之一。
我的理解是這樣的,正則表達式是,在口頭上,

split ((if '-' is before (unless ('\-' is before))) or (if '-' is after (unless ('\-' is before))))

爲什麼不應該的最後一部分是「除非\是前」?如果' - '在之後,這意味着我們在'\'和' - '之間,所以只有\應該在之前,而不是\\-,但它不起作用,如果我改變正則表達式來反映如下:

((?<=-(?!(?<=\\-))) | (?=-(?!(?<=\\)))) 

結果:a-b\-c

,這是什麼原因呢?我在推理中的錯誤在哪裏?

+0

你知道的,也有負面lookbehinds – fge

回答

0

爲什麼不應該最後一部分是「除非\是在之前」?

(?=-(?!(?<=\\-)))) 
    ^here 

光標-經過這麼"unless \ is before"將永遠是假的,因爲我們總是當前位置之前有-


也許更容易的正則表達式將

(?<=(?<!\\\\)-)|(?=(?<!\\\\)-)

  • (?<=(?<!\\\\)-)將檢查如果我們-後,以前沒有\
  • (?=(?<!\\\\)-)將檢查我們是否在-之前沒有\
+0

啊,我沒有知道嗎?=移動光標,我對於正則表達式還很新。另外,你的簡單示例看起來更好,謝謝! – pemko

+0

@pemko BTW所有[look-around](http://www.regular-expressions.info/lookaround.html)機制都是零寬度。這意味着他們可以在需要的時候移動光標,同時檢查他們的條件,但是在退出光標後,光標將被重置到在查找開始之前的位置。 – Pshemo

1

儘管這並沒有真正回答這個問題,但這解釋了周邊環境如何工作。

Lookarounds是錨點:它們不消耗文本,但在輸入文本中找到位置。您正則表達式可以寫在一個更簡單的方式:

(?<=-)(?<!\\-)|(?=-)(?<!\\) 

你這裏有四個lookarounds:正面和負面的回顧後,正面和負面的前瞻。

完整的正則表達式如下:

(?<=-)   # Find a position where what precedes is a dash 
(?<!\\-)   # Find a position where what precedes is not \- 
|     # Or 
(?=-)    # Find a position where what follows is a dash 
(?<!\\)   # Find a position where what precedes is not a \ 

注意術語 「位置」。請注意,將不會在前進文本中。現在

,如果我們試圖匹配該正則表達式對a-b\-c

# Step 1 
# Input: | a-b\-c| 
# Position: |^  | 
# Regex: | (?<=-)(?<!\\-)|(?=-)(?<!\\)| 
# Position: |^       | 
# No match, try other alternative 
# Input: | a-b\-c| 
# Position: |^  | 
# Regex: |(?<=-)(?<!\\-)| (?=-)(?<!\\)| 
# Position: |    ^   | 
# No match, regex fails 
# Advance one position in the input text and try again 

# Step 2 
# Input: |a -b\-c| 
# Position: |^ | 
# Regex: | (?<=-)(?<!\\-)|(?=-)(?<!\\)| 
# Position: |^       | 
# No match, try other alternative 
# Input: |a -b\-c| 
# Position: |^ | 
# Regex: |(?<=-)(?<!\\-)| (?=-)(?<!\\)| 
# Position: |    ^   | 
# Match: a "-" follows 
# Input: |a -b\-c| 
# Position: |^ | 
# Regex: |(?<=-)(?<!\\-)|(?=-) (?<!\\)| 
# Position: |     ^  | 
# Match: what precedes is not a \ 
# Input: |a -b\-c| 
# Position: |^ | 
# Regex: |(?<=-)(?<!\\-)|(?=-)(?<!\\) | 
# Position: |       ^| 
# Regex is satisfied 

這裏是一個不使用分離的替代,沒有lookarounds:

[a-z]+(\\-[a-z]+)*|- 

您可以在使用正則表達式Pattern and use a Matcher

public static void main(final String... args) 
{ 
    final Pattern pattern 
     = Pattern.compile("[a-z]+(\\\\-[a-z]+)*|-"); 

    final Matcher m = pattern.matcher("a-b\\-c"); 
    while (m.find()) 
     System.out.println(m.group()); 
} 
+0

你的正則表達式的簡化是一個我最喜歡的,因爲它是最容易理解的。感謝您的長時間解釋,非常感謝。我會將你的答案標記爲正確的,但是Pshemo確實直接回答了這個問題,所以公平地說,它屬於他。希望你不介意。 – pemko

+0

我不介意;)主要部分是它現在對你有用;) – fge

相關問題