Domanda

Ho un file che contiene diverse linee simili a:

Name: Peter
Address: St. Serrano número 12, España
Country: Spain

E ho bisogno di estrarre l'indirizzo utilizzando un'espressione regolare, tenendo conto che essa può contenere punti, caratteri speciali (ñ, ç), AEIOU ...

Il codice attuale funziona, ma sembra abbastanza brutto:.

Pattern p = Pattern.compile("^(.+?)Address: ([a-zA-Z0-9ñÑçÇáéíóú., ]+)(.+?)$",
                            Pattern.MULTILINE | Pattern.DOTALL);
Matcher m = p.matcher(content);
if (m.matches()) { ... }

Modifica: Il campo Indirizzo potrebbe anche essere diviso in più righe

Name: Peter
Address: St. Serrano número 12,   
Madrid
España
Country: Spain

Modifica:. Non posso usare un oggetto o di proprietà di un parser YAML, come il file contiene altri tipi di informazioni, anche

È stato utile?

Soluzione

Non so oggetti regex di Java che bene, ma qualcosa di simile modello lo farò:

^Address:\s*((?:(?!^\w+:).)+)$

assumendo modalità multilinea e dotall sono.

Questa corrisponderà a qualsiasi riga che inizia con Indirizzo, seguita da nulla fino a quando un carattere di nuova riga e una sola parola seguito da due punti.

Se si conosce il campo successivo deve essere "Paese", è possibile semplificare questo un po ':

^Address:\s*((?:(?!^Country:).)+)$

Il trucco sta nel asserzione che guarda avanti nel gruppo ripetuto. '(?!Nazione:).' corrisponderà tutto tranne l'inizio della stringa 'Paese:', quindi abbiamo solo bastone in non cattura parentesi (:? ...). e quantificare con +, poi gruppo tutto questo in normali parentesi di cattura

Altri suggerimenti

Si potrebbe voler guardare in Properties classe invece di regex. Esso fornisce il modo di gestire i file di testo o XML semplici per rappresentare coppie chiave-valore.

Così si può leggere nel file di esempio e quindi ottenere i valori in questo modo dopo il caricamento di un oggetto Properties:

Properties properties = new Properties();
properties.load(/* InputStream of your file */);

Assert.assertEquals("Peter", properties.getProperty("Name"));
Assert.assertEquals("St. Serrano número 12, España", properties.getProperty("Address"));
Assert.assertEquals("Spain", properties.getProperty("Country"));

Supponendo "contenuto" è una stringa contenente il contenuto del file, il problema principale è che si sta utilizzando matches() dove si dovrebbe usare find().

Pattern p = Pattern.compile("^Address:\\s*(.*)$", Pattern.MULTILINE);
Matcher m = p.matcher(content);
if ( m.find() )
{
  ...
}

Sembra che ci sia una certa confusione in altre risposte sulle modalità multline e dotall. MULTILINE è ciò che permette le ancore ^ e $ corrispondono all'inizio e alla fine, rispettivamente di una linea logica. DOTALL lascia il punto (periodo, punto e basta, a prescindere) linea partita caratteri separatori come \n (avanzamento riga) e \r (ritorno a capo). Questa espressione regolare deve modalità di utilizzo MULTILINE e non deve Modalità uso DOTALL.

Non voglio dire di essere un bastone nel fango, ma non è necessario utilizzare una regex? Perché non risparmiare il vostro sé futuro (o altri) il mal di testa e fare:

String line = reader.readLine();
while(line != null)
{
    line = line.trim();
    if(line.startsWith("Address: "))
    {
        return line.substr("Address: ".length()).trim();
    }
    line = reader.readLine();
}
return null;

Naturalmente questo può essere parametrizzata un po 'come bene e messo in un metodo.

In caso contrario, mi piacerebbe secondo le proprietà o JYaml suggerimenti.

Non una persona di Java, ma non sarebbe un'opera "Address: (.*)$"?

Modifica: Senza il Pattern.MULTILINE | opzione Pattern.DOTALL dovrebbe corrispondere solo su quella linea.

Può contenere una nuova linea? Se non riesce a contenere un ritorno a capo, non è necessario utilizzare il modificatore multilinea, e può fare al posto

Pattern p = Pattern.compile("^Address: (.*)$");

Se è possibile, in alternativa mi viene in mente è

Pattern p = Pattern.compile("Address: (.*)\nCountry", Pattern.MULTILINE);

Senza la DOTALL, il punto sarà non corrisponde un ritorno a capo, in modo da poter specificare esplicitamente nella regexp, che consente di fare quello che hai chiesto.

Si dovrebbe verificare YAML .

Si potrebbe provare a JYaml .

Il meglio di tutto ciò che ha implementazioni in molte lingue.

ps Ho provato il testo di esempio nel YAML :: XS , e funziona perfettamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top