2016-04-15 32 views
0

我在這裏看到一個SO問題,它使用Java MatcherPattern試圖突出顯示文本,類似於Regex101突出顯示的內容。他的規範是在JTextArea中突出顯示任何沒有使用文字字符'#'的字符串。我要建議創建自己的Matcher然後OP刪除他的問題:(正則表達式來抓取「WORD」,除了「#」之後

這是背景,現在這裏是我的問題。我如何使用正則表達式來抓住文字字符串,除非它是(但不相鄰必要)中的線的特定的字符串/字符?

實施例,如果我想選擇從以下

測試儀字符串「測試器」,#tester

測試儀測試#測試儀

測試儀

我希望我的正則表達式將選擇

測試儀,#tester

測試#測試儀

測試儀

但不是最後的「測試者」。

使用Regex101,我得到的距離最近的是/(?=tester)(?<!#)tester/g,但是由於我無法做到「動態」,因此選擇了最後一個「測試」字符串。 (非零)長度回顧,據我所知。

編輯:

我的問題是不特定於Java,否則我會放置在Java標籤。除非Regex101錯誤,我不能使用Limiting Repetition,因爲「Lookbehinds需要爲零寬度,因此量詞不被允許」。

我在Java中測試WiktorStribiżew正則表達式,它工作正常。看到它是一個評論,而不是一個答案,我所能做的就是+1它,Java字符串是(?<!#.{0,1000})\\btester\\b。我測試了它對以下Java字符串tester, #tester\ntest tester # test testern\tester

側面的問題,沒有完全定義的方式來處理跨所有語言的正則表達式?或者是Regex101只是一個糟糕的測試工具(我正在使用它們的默認PHP引擎)?

我會考慮在未來使用RegexStormRegexHero

+0

https://regex101.com/r/aT3qN3/6 – Shafizadeh

+0

那麼它必須是隻有一個字符,這是該字符串唯一。 –

+0

爲什麼你不能簡單地測試你想要的角色? /(?= tester)#?/ g –

回答

0

您可以在tester之前使用一個可選組,並以#開頭。然後檢查第一組的存在並相應地進行替換。

String text = "tester, #tester\ntester foo\ntest tester # test tester\ntester"; 
Pattern p = Pattern.compile("(#[^#\n]*)?(\\btester\\b)"); 
Matcher m = p.matcher(text); 

StringBuffer sb = new StringBuffer(); 
while(m.find()) { 
    if (m.group(1) == null) 
     m.appendReplacement(sb, "<em>" + m.group(2) + "</em>"); 
    else 
     m.appendReplacement(sb, m.group()); 
} 
m.appendTail(sb); 
System.err.println(sb); 

輸出:

<em>tester</em>, #tester 
<em>tester</em> foo 
test <em>tester</em> # test tester 
<em>tester</em> 
0

雖然我原本以爲這是更多強調的比賽在Java中,這個代碼我發現here可以解決所有的問題。略加改變,以配合您的例子:

JTextArea textArea = new JTextArea(10, 30); 

    String text = "test tester # test tester"; 

    textArea.setText(text); 

    Highlighter highlighter = textArea.getHighlighter(); 
    HighlightPainter painter = 
     new DefaultHighlighter.DefaultHighlightPainter(Color.pink); 
    int p0 = text.indexOf("tester"); 
    int p1 = p0 + "tester".length(); 
    highlighter.addHighlight(p0, p1, painter); 

    JOptionPane.showMessageDialog(null, new JScrollPane(textArea)); 

如果你只適用高亮時p0==0text.charAt(p0-1) != '#'你不會需要一個正則表達式。 (或當p0 < text.indexOf("#"),我不知道你想要什麼。)

1

在Java中,你可以利用一個約束的寬度回顧後這是方便的,如果字符的預期子前的數量不是無限的。這意味着你可以在向後看中使用限制量詞。 (有一個錯誤,允許在Java 8中使用*,但由於在更高版本中該錯誤可能已修復,所以不宜使用它。)請注意,如果限制量詞中的值較大,則性能可能會下降。

所以,你可以使用

String rx = "(?<!#.{0,1000})\\btester\\b"; 

IDEONE demo

模式中的任何整字tester匹配(如\b是一個字的邊界)並沒有前面有一個#隨後用0到1000任何字符,但換行符(與DOTALL,它也將匹配換行符)。

在線測試儀的注意事項:因爲regex101不支持正則表達式(如Java或ICU),它具有約束寬度的後顧之憂。使用基於.NET的在線測試器,如RegexStormRegexHero。或只需使用最好的Java正則表達式在線測試人員:RegexPlanetocpsoft


現在, 談論一個通用的解決方案Match what you do not need, and match and capture what you need to keep.

這是the pattern

#.*\btester\b|\b(tester)\b 

注意,綠色高亮tester s爲那些駐留在捕獲組#1,和那些在0組是在藍色在regex101。您可以檢查這些子值屬於哪個組,並在代碼中採取適當的操作。

在Java中,檢查組一致,只是用

if (match.group(1) != null) { 
    /* Group 1 matched, the tester we need is here */ 
} 
else { 
    /* No action, this tester is preceded with # */ 
} 
+0

我用最通用的方法更新了。 –