Cara mengekstrak substring menggunakan regex

382

Saya memiliki string yang memiliki dua tanda kutip tunggal di dalamnya, 'karakter. Di antara tanda kutip tunggal adalah data yang saya inginkan.

Bagaimana saya bisa menulis regex untuk mengekstrak "data yang saya inginkan" dari teks berikut?

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

Jawaban:

569

Dengan asumsi Anda menginginkan bagian antara tanda kutip tunggal, gunakan ungkapan reguler ini dengan Matcher:

"'(.*?)'"

Contoh:

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

Hasil:

data yang saya inginkan
Mark Byers
sumber
12
Sial .. saya selalu lupa tentang modifier non serakah :(
Mihai Toader
33
ganti "jika" dengan "sementara" ketika Anda mengharapkan lebih dari satu kejadian
OneWorld
14
ingat bahwa matcher.find () diperlukan agar sampel kode ini berfungsi. gagal memanggil metode ini akan menghasilkan pengecualian "Tidak ditemukan cocok" ketika matcher.group (1) dipanggil.
rexford
25
Grup @mFontoura (0) akan mengembalikan kecocokan lengkap dengan bagian luar ''. grup (1) mengembalikan apa yang ada di antara '' tanpa '' sendiri.
tagy22
6
@Larry ini balasan yang terlambat, tapi? dalam hal ini adalah pengubah non-serakah, sehingga untuk this 'is' my 'data' with quotesitu akan berhenti lebih awal dan kembali isbukannya mencocokkan karakter sebanyak mungkin dan kembali is' my 'data, yang merupakan perilaku default.
Timekiller
68

Anda tidak perlu regex untuk ini.

Tambahkan apache commons lang ke proyek Anda ( http://commons.apache.org/proper/commons-lang/ ), lalu gunakan:

String dataYouWant = StringUtils.substringBetween(mydata, "'");
Beothorn
sumber
12
Anda harus mempertimbangkan bagaimana perangkat lunak Anda akan didistribusikan. Jika itu seperti webstart, tidak bijaksana untuk menambahkan Apache commons hanya untuk menggunakan fungsionalitas yang satu ini. Tapi mungkin tidak. Selain itu Apache commons memiliki lebih banyak hal untuk ditawarkan. Meskipun sulit untuk mengetahui regex, Anda harus berhati-hati kapan menggunakannya. Regex bisa sangat sulit dibaca, ditulis, dan didebug. Mengingat beberapa konteks menggunakan ini bisa menjadi solusi yang lebih baik.
Beothorn
3
Terkadang StringUtils sudah ada di sana, dalam hal ini solusi ini jauh lebih bersih dan mudah dibaca.
Gábor Nagy
7
Ini seperti membeli mobil untuk melakukan perjalanan 5 mil (ketika Anda bepergian hanya sekali dalam setahun).
prayagupd
Sementara substring mencari string atau nilai tertentu, regex mencari format. Semakin dinamis. Anda perlu regex, jika Anda mencari pola, bukan nilai khusus.
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
sumber
2
System.out.println (matcher.group (0)); <--- Indeks berbasis nol
nclord
4
Grup (0) memiliki arti khusus, grup penangkap mulai dari grup indeks (1) (yaitu grup (1) benar dalam jawabannya). "Grup pengambilan diindeks dari kiri ke kanan, mulai dari satu. Grup nol menunjukkan seluruh pola" - Sumber: docs.oracle.com/javase/8/docs/api/java/util/regex/…
Apriori
12

Ada satu kalimat sederhana untuk ini:

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

Dengan menjadikan grup yang cocok sebagai opsional, ini juga melayani kuotasi yang tidak ditemukan dengan mengembalikan blanko dalam hal itu.

Lihat demo langsung .

Bohemian
sumber
10

Karena Anda juga menandai Scala, solusi tanpa regex yang dengan mudah menangani beberapa string yang dikutip:

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
sumber
4
Jadi solusi yang mudah dibaca, itulah sebabnya orang-orang menyukai scala I belive :)
prayagupd
3
Mengapa tidak hanya .split('\'').get(2)atau sesuatu sejauh itu di Jawa? Saya pikir Anda mungkin perlu memindai otak jika Anda pikir itu solusi yang mudah dibaca - sepertinya seseorang sedang mencoba melakukan beberapa kode golf kepada saya.
ArtOfWarfare
7
String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");
ZehnVon12
sumber
4

seperti pada javascript:

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

regexp yang sebenarnya adalah: /'([^']+)'/

jika Anda menggunakan pengubah non serakah (seperti posting lain) itu seperti ini:

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

ini lebih bersih.

Mihai Toader
sumber
2

Di 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
sumber
1

Apache Commons Lang menyediakan sejumlah utilitas pembantu untuk java.lang API, terutama metode manipulasi String. Dalam kasus Anda, awal dan akhir substring adalah sama, jadi panggil saja fungsi berikut.

StringUtils.substringBetween(String str, String tag)

Mendapat String yang bersarang di antara dua instance dari String yang sama .

Jika awal dan akhir substring berbeda maka gunakan metode kelebihan beban berikut.

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

Mendapat String yang bersarang di antara dua String.

Jika Anda ingin semua contoh substring yang cocok, gunakan,

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

Mencari String untuk substring yang dibatasi oleh tag awal dan akhir, mengembalikan semua substring yang cocok dalam array .

Sebagai contoh dalam pertanyaan untuk mendapatkan semua instance dari substring yang cocok

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

Anda dapat menggunakan ini saya gunakan saat loop untuk menyimpan semua pertandingan substring dalam array jika Anda menggunakan

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

Anda akan mendapatkan substring pertandingan sehingga Anda dapat menggunakan ini untuk mendapatkan semua substring pertandingan

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
sumber
0

tambahkan apache.commons ketergantungan pada pom.xml Anda

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

Dan kode di bawah ini berfungsi.

StringUtils.substringBetween(String mydata, String "'", String "'")
Ganesha
sumber
0

Beberapa cara grup (1) tidak bekerja untuk saya. Saya menggunakan grup (0) untuk menemukan versi url.

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
sumber