Utilizzo di Java per trovare la sottostringa di una stringa più grande usando Regular Expression


140

Se ho una stringa come questa:

FOO[BAR]

Ho bisogno di un modo generico per estrarre la stringa "BAR" dalla stringa in modo che, indipendentemente da quale stringa si trovi tra parentesi quadre, sia in grado di ottenere la stringa.

per esempio

FOO[DOG] = DOG
FOO[CAT] = CAT

Risposte:


253

Dovresti essere in grado di utilizzare quantificatori non avidi, in particolare * ?. Probabilmente vorrai quanto segue:

Pattern MY_PATTERN = Pattern.compile("\\[(.*?)\\]");

Questo ti darà uno schema che corrisponderà alla tua stringa e inserirà il testo tra parentesi quadre nel primo gruppo. Dai un'occhiata alla Documentazione API Pattern per ulteriori informazioni.

Per estrarre la stringa, è possibile utilizzare qualcosa di simile al seguente:

Matcher m = MY_PATTERN.matcher("FOO[BAR]");
while (m.find()) {
    String s = m.group(1);
    // s now contains "BAR"
}

16
Vale la pena ricordare che se c'è una nuova riga tra parentesi quadre, questo fallirà e dovresti usare il flag Pattern.DOTALL per evitarlo.
cletus

Usando il modello sopra, come lo useresti per estrarre la stringa contenente la stringa BAR? Sto guardando l'API Pattern e l'API Matcher ma non sono ancora sicuro di come ottenere la stringa stessa.
digiarnie

@cletus: buona chiamata! @digiarnie: ho aggiunto una revisione alla risposta che contiene un po 'di codice per ottenere la corrispondenza.
Bryan Kyle

30

il modo non regex:

String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf("["),input.indexOf("]"));

in alternativa, per prestazioni / utilizzo della memoria leggermente migliori (grazie a Hosam):

String input = "FOO[BAR]", extracted;
extracted = input.substring(input.indexOf('['),input.lastIndexOf(']'));

1
Vorrei lastIndexOf(']')invece utilizzare , che gestirà parentesi annidate. Inoltre, credo che usare il indexOf(char)sarebbe più veloce di indexOf(String).
Hosam Aly,

Prego. Anche la tua nota sulle prestazioni è molto rilevante, poiché lastIndexOfsarà sicuramente più veloce trovare la parentesi di chiusura.
Hosam Aly,

3
che cosa è più veloce, indexof sottostringa ecc ecc o regexp?
Toskan,

2
vedi il valore di Amit per "estratto" di seguito: input.indexOf ('[') + 1
gcbound

28

Questo è un esempio funzionante:

RegexpExample.java

package org.regexp.replace;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class RegexpExample
{
    public static void main(String[] args)
    {
        String string = "var1[value1], var2[value2], var3[value3]";
        Pattern pattern = Pattern.compile("(\\[)(.*?)(\\])");
        Matcher matcher = pattern.matcher(string);

        List<String> listMatches = new ArrayList<String>();

        while(matcher.find())
        {
            listMatches.add(matcher.group(2));
        }

        for(String s : listMatches)
        {
            System.out.println(s);
        }
    }
}

Visualizza:

value1
value2
value3

6
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public static String get_match(String s, String p) {
    // returns first match of p in s for first group in regular expression 
    Matcher m = Pattern.compile(p).matcher(s);
    return m.find() ? m.group(1) : "";
}

get_match("FOO[BAR]", "\\[(.*?)\\]")  // returns "BAR"

public static List<String> get_matches(String s, String p) {
    // returns all matches of p in s for first group in regular expression 
    List<String> matches = new ArrayList<String>();
    Matcher m = Pattern.compile(p).matcher(s);
    while(m.find()) {
        matches.add(m.group(1));
    }
    return matches;
}

get_matches("FOO[BAR] FOO[CAT]", "\\[(.*?)\\]")) // returns [BAR, CAT]

5

Se hai semplicemente bisogno di ottenere qualsiasi cosa sia tra [], puoi usare in \[([^\]]*)\]questo modo:

Pattern regex = Pattern.compile("\\[([^\\]]*)\\]");
Matcher m = regex.matcher(str);
if (m.find()) {
    result = m.group();
}

Se è necessario che sia del modulo, identifier + [ + content + ]è possibile limitare l'estrazione del contenuto solo quando l'identificatore è alfanumerico:

[a-zA-Z][a-z-A-Z0-9_]*\s*\[([^\]]*)\]

Ciò convaliderà cose come Foo [Bar], o myDevice_123["input"]per esempio.

Problema principale

Il problema principale è quando vuoi estrarre il contenuto di qualcosa del genere:

FOO[BAR[CAT[123]]+DOG[FOO]]

Il Regex non funzionerà e tornerà BAR[CAT[123e FOO.
Se cambiamo Regex in \[(.*)\]allora siamo a posto ma, se stai cercando di estrarre il contenuto da cose più complesse come:

FOO[BAR[CAT[123]]+DOG[FOO]] = myOtherFoo[BAR[5]]

Nessuno dei Regex funzionerà.

Il Regex più accurato per estrarre il contenuto corretto in tutti i casi sarebbe molto più complesso in quanto dovrebbe bilanciare le []coppie e darti il ​​loro contenuto.

Una soluzione più semplice

Se i tuoi problemi stanno diventando complessi e il contenuto []dell'arbitrario, potresti invece bilanciare le coppie di []ed estrarre la stringa usando semplicemente il vecchio codice rathe di un Regex:

int i;
int brackets = 0;
string c;
result = "";
for (i = input.indexOf("["); i < str.length; i++) {
    c = str.substring(i, i + 1);
    if (c == '[') {
        brackets++;
    } else if (c == ']') {
        brackets--;
        if (brackets <= 0) 
            break;
    }
    result = result + c;
}   

Questo è più pseudo-codice che codice reale, non sono un programmatore Java quindi non so se la sintassi è corretta, ma dovrebbe essere abbastanza facile da migliorare.
Ciò che conta è che questo codice dovrebbe funzionare e permetterti di estrarre il contenuto di [], per quanto complesso sia.


2

Penso che la tua espressione regolare sarebbe simile a:

/FOO\[(.+)\]/

Supponendo che l'UFAM sarà costante.

Quindi, per dirlo in Java:

Pattern p = Pattern.compile("FOO\\[(.+)\\]");
Matcher m = p.matcher(inputLine);

FOO [BAR] FOO [BAZ] -> con la tua regex tornerà: "BAR] FOO [BAZ"
Mohammad Jafar Mashhadi

1
String input = "FOO[BAR]";
String result = input.substring(input.indexOf("[")+1,input.lastIndexOf("]"));

Questo restituirà il valore tra il primo '[' e l'ultimo ']'

Foo [Bar] => Bar

Foo [Bar [test]] => Bar [test]

Nota: è necessario aggiungere un errore verificando se la stringa di input non è ben formata.


0

supponendo che nessun'altra parentesi quadra di chiusura sia consentita all'interno, / FOO \ [([^ \]] *) \] /


0

Definirei che desidero un numero massimo di caratteri non] tra [e ]. Questi devono essere sfuggiti alle barre rovesciate (e in Java, questi devono essere sfuggiti di nuovo), e la definizione di non-] è una classe di caratteri, quindi dentro [e ](cioè [^\\]]). Il risultato:

FOO\\[([^\\]]+)\\]

0

In questo modo funziona se si desidera analizzare alcune stringhe che provengono da mYearInDB.toString () = [2013], darà 2013

Matcher n = MY_PATTERN.matcher("FOO[BAR]"+mYearInDB.toString());
while (n.find()) {
 extracredYear  = n.group(1);
 // s now contains "BAR"
    }
    System.out.println("Extrated output is : "+extracredYear);

0

Questo regexp funziona per me:

form\[([^']*?)\]

esempio:

form[company_details][0][name]
form[company_details][0][common_names][1][title]

produzione:

Match 1
1.  company_details
Match 2
1.  company_details

Testato su http://rubular.com/


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.