Come estrarre una sottostringa usando regex


382

Ho una stringa che contiene due virgolette singole, il 'personaggio. Tra le virgolette singole ci sono i dati che voglio.

Come posso scrivere una regex per estrarre "i dati che voglio" dal seguente testo?

mydata = "some string with 'the data i want' inside";

Risposte:


569

Supponendo che tu voglia la parte tra virgolette singole, usa questa espressione regolare con un Matcher:

"'(.*?)'"

Esempio:

String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}

Risultato:

i dati che desidero

12
accidenti .. mi dimentico sempre del modificatore non avido :(
Mihai Toader,

33
sostituisci "if" con un "while" quando ti aspetti più di una occorrenza
OneWorld

14
tenere presente che matcher.find () è necessario per far funzionare questo esempio di codice. la mancata chiamata a questo metodo comporterà un'eccezione "Nessuna corrispondenza trovata" quando viene chiamato matcher.group (1).
Rexford,

25
Il gruppo @mFontoura (0) restituisce la corrispondenza completa con l'esterno ''. group (1) restituisce ciò che è tra '' senza '' stessi.
tagy22,

6
@Larry questa è una risposta tardiva, ma? in questo caso è un modificatore non avido, in modo che this 'is' my 'data' with quotessi fermi presto e ritornasse isinvece di abbinare il maggior numero possibile di caratteri e restituire is' my 'data, che è il comportamento predefinito.
Timekiller,

68

Non hai bisogno di regex per questo.

Aggiungi apache commons lang al tuo progetto ( http://commons.apache.org/proper/commons-lang/ ), quindi usa:

String dataYouWant = StringUtils.substringBetween(mydata, "'");

12
Devi tenere conto di come verrà distribuito il tuo software. Se è qualcosa come un webstart non è saggio aggiungere i comuni Apache solo per usare questa funzionalità. Ma forse non lo è. Inoltre Apache commons ha molto altro da offrire. Anche duro è buono a conoscere regex, devi essere attento a quando usarlo. Regex può essere davvero difficile da leggere, scrivere e eseguire il debug. Dato un po 'di contesto, questo potrebbe essere la soluzione migliore.
Beothorn,

3
A volte StringUtils è già lì, in quei casi questa soluzione è molto più pulita e leggibile.
Gábor Nagy,

7
È come comprare un'auto per percorrere 5 miglia (quando si viaggia solo una volta all'anno).
prayagupd

Mentre la sottostringa cerca una stringa o un valore specifici, regex cerca un formato. È sempre più dinamico. Hai bisogno di regex, se stai cercando uno schema anziché un valore speciale.
burakhan alkan,

14
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".*'([^']*)'.*");
        String mydata = "some string with 'the data i want' inside";

        Matcher matcher = pattern.matcher(mydata);
        if(matcher.matches()) {
            System.out.println(matcher.group(1));
        }

    }
}

2
System.out.println (matcher.group (0)); <--- Indice a base zero
nclord,

4
No. gruppo (0) ha un significato speciale, i gruppi di acquisizione iniziano dal gruppo indice (1) (ovvero il gruppo (1) è corretto nella risposta). "I gruppi di acquisizione sono indicizzati da sinistra a destra, a partire da uno. Il gruppo zero indica l'intero modello" - Fonte: docs.oracle.com/javase/8/docs/api/java/util/regex/…
Apriori

12

C'è un semplice one-liner per questo:

String target = myData.replaceAll("[^']*(?:'(.*?)')?.*", "$1");

Rendendo facoltativo il gruppo corrispondente, ciò provvede anche alle virgolette che non vengono trovate restituendo uno spazio in quel caso.

Guarda la demo dal vivo .


10

Perché hai anche selezionato Scala, una soluzione senza regex che si occupa facilmente di più stringhe tra virgolette:

val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)

res: Array[java.lang.String] = Array(the data i want, and even more data)

4
Soluzione così leggibile, ecco perché la gente ama Scala I
Belive

3
Perché non solo .split('\'').get(2)o qualcosa del genere in Java? Penso che potresti aver bisogno di fare una scansione del cervello se pensi che sia una soluzione leggibile - sembra che qualcuno stia cercando di farmi un po 'di golf.
ArtOfWarfare il

7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");

4

come in javascript:

mydata.match(/'([^']+)'/)[1]

l'attuale regexp è: /'([^']+)'/

se usi il modificatore non avido (come per un altro post) è così:

mydata.match(/'(.*?)'/)[1]

è più pulito.


2

Alla Scala,

val ticks = "'([^']*)'".r

ticks findFirstIn mydata match {
    case Some(ticks(inside)) => println(inside)
    case _ => println("nothing")
}

for (ticks(inside) <- ticks findAllIn mydata) println(inside) // multiple matches

val Some(ticks(inside)) = ticks findFirstIn mydata // may throw exception

val ticks = ".*'([^']*)'.*".r    
val ticks(inside) = mydata // safe, shorter, only gets the first set of ticks


1

Apache Commons Lang offre una serie di utility di supporto per l'API java.lang, in particolare i metodi di manipolazione delle stringhe. Nel tuo caso, le sottostringhe iniziale e finale sono le stesse, quindi chiama la seguente funzione.

StringUtils.substringBetween(String str, String tag)

Ottiene la stringa nidificata tra due istanze della stessa stringa .

Se le sottostringhe iniziale e finale sono diverse, utilizzare il seguente metodo sovraccarico.

StringUtils.substringBetween(String str, String open, String close)

Ottiene la stringa nidificata tra due stringhe.

Se vuoi tutte le istanze delle sottostringhe corrispondenti, usa,

StringUtils.substringsBetween(String str, String open, String close)

Cerca una stringa per sottostringhe delimitate da un tag di inizio e fine, restituendo tutte le sottostringhe corrispondenti in un array .

Per l'esempio in questione ottenere tutte le istanze della sottostringa corrispondente

String[] results = StringUtils.substringsBetween(mydata, "'", "'");

0

puoi usare questo che uso while loop per memorizzare tutte le corrispondenze sottostringa nell'array se usi

if (matcher.find()) { System.out.println(matcher.group(1)); }

otterrai la sottostringa delle partite in modo da poterla utilizzare per ottenere la sottostringa di tutte le partite

Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+").matcher(text);
   // Matcher  mat = pattern.matcher(text);
    ArrayList<String>matchesEmail = new ArrayList<>();
        while (m.find()){
            String s = m.group();
            if(!matchesEmail.contains(s))
                matchesEmail.add(s);
        }

    Log.d(TAG, "emails: "+matchesEmail);

0

aggiungi la dipendenza apache.commons dal tuo pom.xml

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

E sotto il codice funziona.

StringUtils.substringBetween(String mydata, String "'", String "'")

0

Alcuni come il gruppo (1) non ha funzionato per me. Ho usato il gruppo (0) per trovare la versione dell'URL.

Pattern urlVersionPattern = Pattern.compile("\\/v[0-9][a-z]{0,1}\\/");
Matcher m = urlVersionPattern.matcher(url);
if (m.find()) { 
    return StringUtils.substringBetween(m.group(0), "/", "/");
}
return "v0";
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.