2016-06-26 14 views
0

Hier fangen ein Beispiel:regex nicht alle Spiele

The two (Senior Officer Stuart & Officer Jess) were intercepted by Officer George. 

Nun lassen Sie uns sagen, ich habe zwei Reihen „Officer“ und „Senior Officer“ und wollen ersetzen den Namen nach ihnen mit einem allgemeinen Token "PERSON". Wie Sie sehen können, gibt es drei Namen, die nach einem Rang Stuart, Jess, George kommen. Ich weiß nicht, warum meine Regex-Lösung nicht alle erfasst. Hier ist mein Code:

public static void main(String[] args) { 
    String input = "The two (Senior Officer Stuart & Officer Jess) were intercepted by Officer George."; 
    ArrayList<String> ranks = new ArrayList<String>(); 
    ranks.add("Senior Officer"); 
    ranks.add("Officer"); 
    for (String rank : ranks) { 
     Pattern pattern = Pattern.compile(".*" + rank + " ([a-zA-Z]*?) .*"); 
     Matcher m = pattern.matcher(input); 
     if (m.find()) { 
      System.out.println(rank); 
      System.out.println(m.group(1)); 
     } 
    } 
} 

und hier ist seine Ausgabe:

Senior Officer 
Stuart 
Officer 
Stuart 

die Stuart zweimal erfasst (über Vorgesetzter und Offizier), ignoriert aber Jess und George. Ich erwarte, dass dies als Ausgabe zu erhalten:

Senior Officer 
Stuart 
Officer 
Stuart 
Officer 
Jess 
Officer 
George 
+0

No regex Experte ausreichend sein, aber der Raum sieht verdächtig: '([ a-zA-Z] *?). * ' –

+0

Und ja, du solltest' while' nicht 'if' verwenden –

+0

Etwas wie ,, ..... 'Pattern.compile (". *? "+ Rang +" ([a-zA-Z] *) ");' –

Antwort

2

Dies wird

for (String rank : ranks) { 
    Pattern pattern = Pattern.compile("\\b" + rank + "\\s+([a-zA-Z]*)"); 
    Matcher m = pattern.matcher(input); 
    while (m.find()) { 
     System.out.println(rank); 
     System.out.println(m.group(1)); 
    } 
} 

Ideone Demo

Regex Aufteilung (Stand Kommentare)

Officer #Match Officer literally 
(#Capturing group 
    (?: #Non-capturing group 
    \s #Match space 
    (?!(?:Senior\s+)?Officer) #Negative lookahead assures that its impossible to match the word Senior(which is optional) and Officer literally 
    [A-Z][a-zA-Z]* #Match capital letter followed by combination of capital and small letter 
)* #Repeat the previous step any number of time till one of the condition of first letter being capital fails or word Officer is found 
) 
+0

Gibt es eine Möglichkeit, zwei/drei Wort Substantive zu fangen? Zum Beispiel in "Senior Officer Eduardo Garcia Lopez", um das gesamte "Eduardo Garcia Lopez" statt des ersten Wortes "Eduardo" zu fangen? – user3639557

+0

@ user3639557 Sie können das ..aber es gibt ein Problem, weil Sie nicht im Voraus bestimmen können, wie viele Wörter zu erfassen – rock321987

+0

Wie wäre es, solange Wörter obere Initiale sind? – user3639557

0

Das for Sie findet nur das erste Spiel eines jeden Ranges verwenden. Zuallererst benötigen Sie eine while-Klausel innerhalb der for.

for (String rank : ranks) { 
     Pattern pattern = Pattern.compile(rank + " [A-z]+"); 
     Matcher m = pattern.matcher(input); 
     while (m.find()) { 
      System.out.println(rank); 
      System.out.println(m.group(1)); 
     } 
    } 

jedoch das löst nicht das Problem der „Senior Officer“ Rang zwei Mal zu finden: einmal, wenn Sie für „Senior Officer“ und einmal suchen, wenn Sie für „Offizier“ suchen. Ich bin mir nicht sicher, wie Sie mit diesem Problem umgehen wollen. Wenn du möchtest, dass Stuart zweimal erscheint, dann ist dieser Code gut genug. Wenn Sie möchten, dass Stuart nur einmal erkannt wird, müssen Sie an Ihrem RegEx arbeiten.

P.S. Verwenden Sie ein Online-Tool, um die Regex vor dem Codieren zu testen. Es spart viel Zeit.

+0

@ user3639557: Er hat recht damit, wann und nicht wenn. 1+ –

+0

@ user3639557 Ich habe die Regex aktualisiert –

Verwandte Themen