So extrahieren Sie einen Teilstring mit Regex

382

Ich habe eine Zeichenfolge, die zwei einfache Anführungszeichen enthält, das 'Zeichen. Zwischen den einfachen Anführungszeichen stehen die Daten, die ich möchte.

Wie kann ich einen regulären Ausdruck schreiben, um "die gewünschten Daten" aus dem folgenden Text zu extrahieren?

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

Antworten:

569

Angenommen, Sie möchten den Teil zwischen einfachen Anführungszeichen verwenden, verwenden Sie diesen regulären Ausdruck mit Matcher:

"'(.*?)'"

Beispiel:

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

Ergebnis:

die Daten, die ich will
Mark Byers
quelle
12
verdammt .. ich vergesse immer den nicht gierigen Modifikator :(
Mihai Toader
33
Ersetzen Sie das "wenn" durch ein "während", wenn Sie mehr als ein Ereignis erwarten
OneWorld
14
Beachten Sie, dass matcher.find () benötigt wird, damit dieses Codebeispiel funktioniert. Wenn diese Methode nicht aufgerufen wird, wird beim Aufruf von matcher.group (1) die Ausnahme "Keine Übereinstimmung gefunden" angezeigt.
Rexford
25
@mFontoura group (0) würde die vollständige Übereinstimmung mit dem äußeren '' zurückgeben. Gruppe (1) gibt zurück, was sich zwischen dem '' ohne das '' selbst befindet.
Tagy22
6
@ Larry das ist eine späte Antwort, aber? In diesem Fall handelt es sich um einen nicht gierigen Modifikator, so dass this 'is' my 'data' with quoteser vorzeitig beendet wird und zurückkehrt, isanstatt so viele Zeichen wie möglich abzugleichen und zurückzukehren is' my 'data, was das Standardverhalten ist.
Timekiller
68

Sie brauchen dafür keinen regulären Ausdruck.

Fügen Sie Ihrem Projekt apache commons lang hinzu ( http://commons.apache.org/proper/commons-lang/ ), und verwenden Sie dann:

String dataYouWant = StringUtils.substringBetween(mydata, "'");
Beothorn
quelle
12
Sie müssen berücksichtigen, wie Ihre Software verteilt wird. Wenn es sich um einen Webstart handelt, ist es nicht ratsam, Apache Commons hinzuzufügen, um nur diese eine Funktionalität zu verwenden. Aber vielleicht ist es nicht. Außerdem hat Apache Commons noch viel mehr zu bieten. Selbst wenn es schwierig ist, Regex zu kennen, muss man vorsichtig sein, wann man es verwendet. Regex kann sehr schwer zu lesen, zu schreiben und zu debuggen sein. In einem bestimmten Kontext könnte dies die bessere Lösung sein.
Beothorn
3
Manchmal ist StringUtils bereits vorhanden. In diesen Fällen ist diese Lösung viel sauberer und lesbarer.
Gábor Nagy
7
Es ist wie ein Auto zu kaufen, um 5 Meilen zu reisen (wenn Sie nur einmal im Jahr reisen).
Prayagupd
Während der Teilstring nach einer bestimmten Zeichenfolge oder einem bestimmten Wert sucht, sucht der reguläre Ausdruck nach einem Format. Es wird immer dynamischer. Sie benötigen Regex, wenn Sie nach einem Muster anstelle eines speziellen Werts suchen.
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));
        }

    }
}
Sean McEligot
quelle
2
System.out.println (matcher.group (0)); <---
Nullbasierter
4
Die Gruppe (0) hat eine besondere Bedeutung. Die Erfassung von Gruppen beginnt bei der Indexgruppe (1) (dh die Gruppe (1) ist in der Antwort korrekt). "Erfassungsgruppen werden von links nach rechts beginnend bei eins indiziert. Gruppe Null bezeichnet das gesamte Muster" - Quelle: docs.oracle.com/javase/8/docs/api/java/util/regex/…
Apriori
12

Dafür gibt es einen einfachen Einzeiler:

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

Wenn Sie die übereinstimmende Gruppe optional machen, wird auch berücksichtigt, dass Anführungszeichen nicht gefunden werden, indem in diesem Fall ein Leerzeichen zurückgegeben wird.

Siehe Live-Demo .

Böhmisch
quelle
10

Weil Sie auch Scala angekreuzt haben, eine Lösung ohne Regex, die sich leicht mit Zeichenfolgen in mehreren Anführungszeichen befasst:

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)
Debilski
quelle
4
So lesbare Lösung, deshalb lieben die Leute Scala, die ich glaube :)
Prayagupd
3
Warum nicht einfach .split('\'').get(2)oder so etwas in Java? Ich denke, Sie müssen möglicherweise einen Gehirn-Scan durchführen, wenn Sie der Meinung sind, dass dies eine lesbare Lösung ist. Es sieht so aus, als hätte jemand versucht, mir Code-Golf zu spielen.
ArtOfWarfare
7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");
ZehnVon12
quelle
4

wie in Javascript:

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

Der eigentliche reguläre Ausdruck ist: /'([^']+)'/

Wenn Sie den nicht gierigen Modifikator verwenden (wie in einem anderen Beitrag beschrieben), ist dies folgendermaßen:

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

es ist sauberer.

Mihai Toader
quelle
2

In 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
Daniel C. Sobral
quelle
2

String dataIWant = mydata.split("'")[1];

Siehe Live-Demo

ZehnVon12
quelle
1

Apache Commons Lang bietet eine Vielzahl von Hilfsprogrammen für die java.lang-API, insbesondere Methoden zur Manipulation von Zeichenfolgen. In Ihrem Fall sind die Start- und End-Teilzeichenfolgen identisch. Rufen Sie einfach die folgende Funktion auf.

StringUtils.substringBetween(String str, String tag)

Ruft den String ab, der zwischen zwei Instanzen desselben Strings verschachtelt ist .

Wenn die Start- und Endunterzeichenfolgen unterschiedlich sind, verwenden Sie die folgende überladene Methode.

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

Ruft den String ab, der zwischen zwei Strings verschachtelt ist.

Wenn Sie alle Instanzen der übereinstimmenden Teilzeichenfolgen möchten, verwenden Sie,

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

Durchsucht einen String nach Teilzeichenfolgen, die durch ein Start- und ein End-Tag begrenzt sind, und gibt alle übereinstimmenden Teilzeichenfolgen in einem Array zurück .

Für das betreffende Beispiel werden alle Instanzen des passenden Teilstrings abgerufen

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

Sie können diese while-Schleife verwenden, um alle übereinstimmenden Teilzeichenfolgen im Array zu speichern, wenn Sie verwenden

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

Sie erhalten einen Übereinstimmungs-Teilstring, mit dem Sie alle Übereinstimmungs-Teilzeichenfolgen abrufen können

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);
Nouh Mohamed
quelle
0

hinzufügen apache.commons Abhängigkeit von Ihrem pom.xml

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

Und unten Code funktioniert.

StringUtils.substringBetween(String mydata, String "'", String "'")
Ganesh
quelle
0

Einige, wie die Gruppe (1) für mich nicht funktioniert hat. Ich habe Gruppe (0) verwendet, um die URL-Version zu finden.

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";
Arindam
quelle