Używanie języka Java do znajdowania podłańcucha większego ciągu za pomocą wyrażenia regularnego


140

Jeśli mam taki ciąg:

FOO[BAR]

Potrzebuję ogólnego sposobu, aby uzyskać ciąg „BAR” z ciągu, tak aby bez względu na to, jaki ciąg znajduje się między nawiasami kwadratowymi, byłby w stanie uzyskać ciąg.

na przykład

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

Odpowiedzi:


253

Powinieneś móc używać niechciwych kwantyfikatorów, a konkretnie * ?. Prawdopodobnie będziesz potrzebować następujących rzeczy:

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

To da ci wzór, który będzie pasował do twojego ciągu i umieści tekst w nawiasach kwadratowych w pierwszej grupie. Zapoznaj się z dokumentacją Pattern API, aby uzyskać więcej informacji.

Aby wyodrębnić ciąg, możesz użyć czegoś takiego:

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

16
Warto wspomnieć, że jeśli między nawiasami kwadratowymi znajduje się nowa linia, zakończy się to niepowodzeniem i aby tego uniknąć, należy użyć flagi Pattern.DOTALL.
cletus

Korzystając z powyższego wzorca, w jaki sposób użyłbyś tego do wyodrębnienia ciągu zawierającego ciąg BAR? Patrzę na API Pattern i Matcher API, ale nadal nie jestem pewien, jak uzyskać sam ciąg.
digiarnie

@cletus: Dobre połączenie! @digiarnie: Dodałem poprawkę do odpowiedzi, która zawiera kod słomkowy do uzyskania dopasowania.
Bryan Kyle

30

sposób bez wyrażeń regularnych:

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

alternatywnie, dla nieco lepszej wydajności / wykorzystania pamięci (dzięki Hosam):

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

1
Chciałbym używać lastIndexOf(']')zamiast, który będzie obsługiwać nawiasów zagnieżdżonych. Ponadto uważam, że użycie programu indexOf(char)byłoby szybsze niż indexOf(String).
Hosam Aly

Nie ma za co. Twoja uwaga na temat wydajności jest również bardzo istotna, ponieważ lastIndexOfz pewnością szybciej będzie znaleźć nawias zamykający.
Hosam Aly

3
co jest szybsze, indeksowanie podciągów itp. itp. czy wyrażenie regularne?
Toskan

2
zobacz wartość Amita dla „wyodrębnionego” poniżej: input.indexOf ('[') + 1
gcbound

28

Oto działający przykład:

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

To pokazuje :

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

Jeśli po prostu potrzebujesz zdobyć to, co jest pomiędzy [], możesz użyć w \[([^\]]*)\]następujący sposób:

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

Jeśli chcesz, aby był w formie identifier + [ + content + ], możesz ograniczyć wyodrębnianie treści tylko wtedy, gdy identyfikator jest alfanumeryczny:

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

Pozwoli to zweryfikować takie rzeczy Foo [Bar], albo myDevice_123["input"]na przykład.

Główna kwestia

Główny problem występuje, gdy chcesz wyodrębnić zawartość czegoś takiego:

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

Regex nie będzie działać i wróci BAR[CAT[123i FOO.
Jeśli zmienimy Regex na, \[(.*)\]wszystko jest w porządku, ale jeśli próbujesz wyodrębnić zawartość z bardziej złożonych rzeczy, takich jak:

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

Żaden z Regexów nie zadziała.

Najdokładniejszy Regex do wyodrębnienia właściwej treści we wszystkich przypadkach byłby znacznie bardziej złożony, ponieważ musiałby zrównoważyć []pary i zapewnić ich zawartość.

Prostsze rozwiązanie

Jeśli twoje problemy stają się coraz bardziej złożone, a zawartość jest []arbitralna, możesz zamiast tego zrównoważyć pary []i wyodrębnić ciąg przy użyciu zwykłego starego kodu zamiast 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;
}   

To jest bardziej pseudokod niż prawdziwy kod, nie jestem koderem Java, więc nie wiem, czy składnia jest poprawna, ale powinno być wystarczająco łatwe do ulepszenia.
Liczy się to, że ten kod powinien działać i pozwalać na wyodrębnienie zawartości [], jakkolwiek jest to skomplikowane.


2

Myślę, że twoje wyrażenie regularne wyglądałoby tak:

/FOO\[(.+)\]/

Zakładając, że inspektor obsługi lotów będzie stały.

Tak więc, aby umieścić to w Javie:

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

FOO [BAR] FOO [BAZ] -> z Twoim wyrażeniem regularnym powróci: „BAR] FOO [BAZ”
Mohammad Jafar Mashhadi

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

To zwróci wartość między pierwszym „[” a ostatnim „]”

Foo [Bar] => Bar

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

Uwaga: należy dodać funkcję sprawdzania błędów, jeśli ciąg wejściowy nie jest poprawnie sformułowany.


0

zakładając, że żaden inny zamykający nawias kwadratowy nie jest dozwolony w obrębie, / FOO \ [([^ \]] *) \] /


0

Zdefiniowałbym, że chcę mieć maksymalną liczbę znaków innych niż] między [a ]. Muszą być one poprzedzone odwrotnym ukośnikiem (aw Javie trzeba je ponownie zmienić), a definicja non-] jest klasą znaków, a więc wewnątrz [i ](tj [^\\]].). Wynik:

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

0

W ten sposób jego praca, jeśli chcesz przeanalizować jakiś ciąg, który pochodzi z mYearInDB.toString () = [2013], da 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

To wyrażenie regularne działa dla mnie:

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

przykład:

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

wynik:

Match 1
1.  company_details
Match 2
1.  company_details

Przetestowano na http://rubular.com/


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.