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

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

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, "'");

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

    }
}

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 .


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)

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

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.


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


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, "'", "'");

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

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 "'")

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";
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.