Menggunakan Java untuk menemukan substring dari string yang lebih besar menggunakan Regular Expression


141

Jika saya memiliki string seperti ini:

FOO[BAR]

Saya memerlukan cara umum untuk mengeluarkan string "BAR" dari string sehingga tidak peduli string apa pun yang ada di antara tanda kurung siku, string itu bisa didapat.

misalnya

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

Jawaban:


257

Anda harus bisa menggunakan bilangan non-serakah, khususnya * ?. Anda mungkin menginginkan yang berikut:

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

Ini akan memberi Anda pola yang akan cocok dengan string Anda dan meletakkan teks di dalam tanda kurung siku di grup pertama. Lihat Dokumentasi API Pola untuk informasi lebih lanjut.

Untuk mengekstrak string, Anda bisa menggunakan sesuatu seperti berikut:

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

16
Perlu disebutkan bahwa jika ada garis baru di antara tanda kurung siku, ini akan gagal dan Anda harus menggunakan flag Pattern.DOTALL untuk menghindarinya.
cletus

Dengan menggunakan pola di atas, bagaimana Anda kemudian menggunakannya untuk mengekstrak string yang berisi string BAR? Saya melihat Pattern API dan Matcher API tapi saya masih tidak yakin bagaimana cara mendapatkan string itu sendiri.
digiarnie

@cletus: Panggilan bagus! @digiarnie: Saya telah menambahkan revisi pada jawaban yang berisi beberapa kode manusia jerami untuk mendapatkan kecocokan.
Bryan Kyle

30

cara non-regex:

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

sebagai alternatif, untuk kinerja / penggunaan memori yang sedikit lebih baik (terima kasih Hosam):

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

1
Saya akan menggunakan lastIndexOf(']')sebagai gantinya, yang akan menangani tanda kurung bersarang. Selain itu, saya percaya menggunakan indexOf(char)akan lebih cepat daripada indexOf(String).
Hosam Aly

Sama-sama. Catatan Anda tentang kinerja juga sangat relevan, karena lastIndexOfpasti akan lebih cepat menemukan braket penutup.
Hosam Aly

3
apa yang lebih cepat, indeks substring dll, atau regexp?
Toskan

2
lihat nilai Amit untuk "diekstrak" di bawah ini: input.indexOf ('[') + 1
gcbound

28

Ini adalah contoh kerja:

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

Ini menampilkan:

value1
value2
value3

7
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

Jika Anda hanya perlu mendapatkan apa pun di antara keduanya [], Anda dapat menggunakan \[([^\]]*)\]seperti ini:

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

Jika Anda membutuhkannya dalam bentuk, identifier + [ + content + ]Anda dapat membatasi ekstraksi konten hanya jika pengenalnya adalah alfanumerik:

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

Ini akan memvalidasi hal-hal seperti Foo [Bar], atau myDevice_123["input"]misalnya.

Isu utama

Masalah utamanya adalah ketika Anda ingin mengekstrak konten dari sesuatu seperti ini:

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

Regex tidak akan berfungsi dan akan kembali BAR[CAT[123dan FOO.
Jika kita mengubah Regex menjadi \[(.*)\]maka kita baik-baik saja tetapi kemudian, jika Anda mencoba mengekstrak konten dari hal-hal yang lebih kompleks seperti:

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

Tak satu pun dari Regex akan berfungsi.

Regex paling akurat untuk mengekstrak konten yang tepat dalam semua kasus akan jauh lebih kompleks karena perlu menyeimbangkan []pasangan dan memberi Anda konten.

Solusi yang lebih sederhana

Jika masalah Anda semakin kompleks dan konten []arbitrer, Anda dapat menyeimbangkan pasangan []dan mengekstrak string menggunakan kode lama biasa daripada 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;
}   

Ini lebih banyak pseudo-code daripada kode asli, saya bukan pembuat kode Java jadi saya tidak tahu apakah sintaksnya benar, tetapi seharusnya cukup mudah untuk diperbaiki.
Yang penting adalah kode ini harus berfungsi dan memungkinkan Anda mengekstrak konten [], betapapun rumitnya itu.


2

Menurut saya ekspresi reguler Anda akan terlihat seperti:

/FOO\[(.+)\]/

Dengan asumsi bahwa FOO akan konstan.

Jadi, untuk meletakkan ini di Java:

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

FOO [BAR] FOO [BAZ] -> dengan regex Anda akan mengembalikan: "BAR] FOO [BAZ"
Mohammad Jafar Mashhadi

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

Ini akan mengembalikan nilai antara '[' dan terakhir ']' pertama

Foo [Bar] => Bar

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

Catatan: Anda harus menambahkan pemeriksaan kesalahan jika string input tidak terbentuk dengan baik.


0

dengan asumsi bahwa tidak ada tanda kurung siku penutup lain yang diperbolehkan di dalam, / FOO \ [([^ \]] *) \] /


0

Saya akan mendefinisikan bahwa saya menginginkan jumlah karakter non-] maksimum antara [dan ]. Ini perlu di-escape dengan garis miring terbalik (dan di Java, ini perlu di-escape lagi), dan definisi non-] adalah kelas karakter, sehingga di dalam [dan ](yaitu [^\\]]). Hasil:

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

0

Seperti ini kerjanya jika Anda ingin mengurai beberapa string yang berasal dari mYearInDB.toString () = [2013] itu akan memberikan 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

Regexp ini berfungsi untuk saya:

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

contoh:

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

keluaran:

Match 1
1.  company_details
Match 2
1.  company_details

Diuji di http://rubular.com/


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.