2013-07-27 11 views
6

Ich versuche, eine Funktion zu schreiben, die jedes Wort aus einem Satz extrahiert, der eine bestimmte Teilzeichenfolge enthält, z. Auf der Suche nach "Po" in "Porky Pork Chop" wird Porky Pork zurückgegeben.Extrahiere jedes vollständige Wort, das eine bestimmte Teilzeichenfolge enthält

Ich habe meine Regex auf Regexpal getestet, aber der Java-Code scheint nicht zu funktionieren. Was mache ich falsch?

private static String foo() 
    { 

     String searchTerm = "Pizza"; 
     String text = "Cheese Pizza"; 

     String sPattern = "(?i)\b("+searchTerm+"(.+?)?)\b"; 
     Pattern pattern = Pattern.compile (sPattern); 
     Matcher matcher = pattern.matcher (text); 
     if(matcher.find()) 
     { 
      String result = "-"; 
      for(int i=0;i < matcher.groupCount();i++) 
      { 
       result+= matcher.group (i) + " "; 
      } 
      return result.trim(); 
     }else 
     { 
      System.out.println("No Luck"); 
     } 
    } 

Antwort

2
  1. In Java passieren \bword boundaries Motor regex Sie es als \\b schreiben müssen. \b steht für die Rücktaste im String-Objekt.

  2. Gemessen an Ihrem Beispiel möchten Sie alle Wörter zurückgeben, die Ihre Teilzeichenfolge enthält. Verwenden Sie dazu nicht for(int i=0;i < matcher.groupCount();i++), sondern while(matcher.find()), da die Gruppenanzahl über alle Gruppen in einer einzelnen Übereinstimmung und nicht über alle Übereinstimmungen iteriert.

  3. Wenn Ihr String einige Sonderzeichen enthalten können Sie wahrscheinlich Pattern.quote(searchTerm)

  4. In Ihrem Code gehe ich davon verwenden, sollten Sie versuchen, "Pizza" in "Cheese Pizza" zu finden, so dass Sie wollen auch Strings finden, die gleiche wie String gesucht . Obwohl Ihr Regex dafür gut funktioniert, können Sie Ihren letzten Teil (.+?)?) zu \\w* ändern und am Anfang \\w* hinzufügen, wenn der Teilstring auch in der Wortmitte gefunden werden soll (nicht nur beim Start).

So kann Ihr Code aussehen

private static String foo() { 

    String searchTerm = "Pizza"; 
    String text = "Cheese Pizza, Other Pizzas"; 

    String sPattern = "(?i)\\b\\w*" + Pattern.quote(searchTerm) + "\\w*\\b"; 
    StringBuilder result = new StringBuilder("-").append(searchTerm).append(": "); 

    Pattern pattern = Pattern.compile(sPattern); 
    Matcher matcher = pattern.matcher(text); 
    while (matcher.find()) { 
     result.append(matcher.group()).append(' '); 
    } 
    return result.toString().trim(); 
} 
+0

Das ist eine wirklich großartige Erklärung! Vielen Dank –

+0

@ downvoter Könnten Sie so freundlich sein und Grund für Ihre Aktion teilen? Es macht mir nichts aus -1, wenn ich es verdiene, also hab keine Angst. – Pshemo

2

Während die regex Ansatz sicherlich eine gültige Methode ist, finde ich es einfacher zu durchdenken, wenn Sie die Wörter durch ein Leerzeichen bis aufgeteilt. Dies kann mit Stringsplit Methode durchgeführt werden.

public List<String> doIt(final String inputString, final String term) { 
    final List<String> output = new ArrayList<String>(); 
    final String[] parts = input.split("\\s+"); 
    for(final String part : parts) { 
     if(part.indexOf(term) > 0) { 
      output.add(part); 
     } 
    } 
    return output; 
} 

Natürlich ist es nichts wert, dass dies tatsächlich zwei Durchgänge durch Ihre Eingabe String tun wird. Der erste Durchlauf, um die Zeichen zu finden, auf die Leerzeichen aufgeteilt werden sollen, und der zweite Durchlauf, der jedes Teilwort für Ihre Teilzeichenfolge durchsucht.

Wenn jedoch ein Durchgang erforderlich ist, ist der Regex-Pfad besser.

+0

Wenn es sich um mehrere Leerzeichen/Endlinien handeln könnte, können Sie trotzdem mit dem Split mit '\\ s +' auskommen. – Thomas

+0

@Thomas danke, ich habe das hinzugefügt. :) –

1

Ich finde nicholas.hauschild 's Antwort, die beste zu sein.

Allerdings, wenn Sie wirklich regex verwenden wollte, könnte man es als solches tun:

String searchTerm = "Pizza"; 
String text = "Cheese Pizza"; 
Pattern pattern = Pattern.compile("\\b" + Pattern.quote(searchTerm) 
     + "\\b", Pattern.CASE_INSENSITIVE); 
Matcher matcher = pattern.matcher(text); 
while (matcher.find()) { 
    System.out.println(matcher.group()); 
} 

Ausgang:

Pizza 
1

Das Muster

sein sollte
String sPattern = "(?i)\\b("+searchTerm+"(?:.+?)?)\\b"; 

Sie wollen um die ganze (Pizza-) Schnur einzufangen. ?: stellt sicher, dass Sie einen Teil der Zeichenfolge nicht zweimal erfassen.

0

Versuchen Sie, diese Muster:

String searchTerm = "Po"; 
String text = "Porky Pork Chop oPod zzz llPo"; 

Pattern p = Pattern.compile("\\p{Alpha}+" + substring + "|\\p{Alpha}+" + substring + "\\p{Alpha}+|" + substring + "\\p{Alpha}+"); 

Matcher m = p.matcher(myString); 

while(m.find()) { 
    System.out.println(">> " + m.group()); 
} 
0

Ok, ich gebe Ihnen ein Muster in rohen Stil (nicht Java-Stil, müssen Sie doppelt entkommen selbst):

(?i)\b[a-z]*po[a-z]*\b 



Und das ist alles .

Verwandte Themen