2013-07-27 14 views
6

Sto provando a scrivere una funzione che estrae ogni parola da una frase che contiene una determinata sottostringa ad es. Se cerchi "Po" in "Porky Pork Chop", restituirai Porky Pork.Estrarre ogni parola completa che contiene una determinata sottostringa

Ho testato la mia espressione regolare su regexpal ma il codice Java non sembra funzionare. Che cosa sto facendo di sbagliato?

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"); 
     } 
    } 

risposta

2
  1. In Java di passare \bword boundaries per regex motore è necessario scrivere come \\b. \b rappresenta il backspace nell'oggetto String.

  2. Giudicando dall'esempio si desidera restituire tutte le parole che contengono la sottostringa. Per fare questo non utilizzare for(int i=0;i < matcher.groupCount();i++) ma while(matcher.find()) poiché il conteggio dei gruppi verrà iterato su tutti i gruppi in una singola corrispondenza, non su tutte le corrispondenze.

  3. Nel caso in cui la stringa può contenere alcuni caratteri speciali che probabilmente dovrebbe usare Pattern.quote(searchTerm)

  4. Nel codice che si sta tentando di trovare "Pizza" in "Cheese Pizza" quindi immagino che anche voi volete trovare stringhe che stesso ha cercato sottostringa . Sebbene la regex funzioni correttamente, puoi modificare l'ultima parte da (.+?)?) a \\w* e aggiungere \\w* all'avvio se anche la sottostringa deve corrispondere a metà della parola (non solo all'inizio).

Così il vostro codice può sembrare

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

Questa è davvero una grande spiegazione! Grazie mille –

+0

@downvoter Potresti essere così gentile e condividere la ragione della tua azione? Non mi importa di -1 quando me lo merito, quindi non aver paura. – Pshemo

2

Mentre l'approccio regex è certamente un valido metodo, lo trovo più facile pensare attraverso quando si dividono le parole da spazi bianchi. Questo può essere fatto con il metodo Stringsplit.

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; 
} 

Ovviamente non vale nulla che fare ciò esegua effettivamente due passaggi tramite l'input String. Il primo passaggio per trovare i caratteri che sono spazi bianchi da dividere, e il secondo passaggio che guarda attraverso ogni parola divisa per la sottostringa.

Se è necessario un passaggio, il percorso regex è migliore.

+0

Se potrebbe trattarsi di più spazi/linee di demarcazione, è ancora possibile passare alla divisione con '\\ s +'. – Thomas

+0

@Thomas grazie, l'ho aggiunto. :) –

1

Trovo la risposta nicholas.hauschild la migliore.

Tuttavia, se davvero voleva utilizzare regex, si potrebbe fare come tale:

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()); 
} 

uscita:

Pizza 
1

Il modello avrebbe dovuto essere

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

Volete per catturare l'intera stringa (pizza). ?: assicura che non si acquisisca una parte della stringa due volte.

0

Prova questo modello:

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, vi do un modello in stile crudo (non java stile, è necessario raddoppiare fuggire da soli):

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



E questo è tutto .

Problemi correlati