Normal İfadeyi kullanarak daha büyük bir dizenin alt dizesini bulmak için Java'yı kullanma


140

Eğer böyle bir dize varsa:

FOO[BAR]

"BAR" dizesini dize dışında olsun ne olursa olsun dize almak için köşeli ayraçlar arasında dize olsun genel bir yol gerekir.

Örneğin

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

Yanıtlar:


253

Açgözlü olmayan niceleyiciler, özellikle *? Muhtemelen aşağıdakileri isteyeceksiniz:

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

Bu size dizenizle eşleşecek ve metni ilk gruptaki köşeli parantezlerin içine yerleştirecek bir desen verecektir. Daha fazla bilgi için Pattern API Belgelerine göz atın .

Dizeyi ayıklamak için aşağıdakine benzer bir şey kullanabilirsiniz:

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

16
Köşeli parantezler arasında yeni bir satır varsa, bunun başarısız olacağını ve bundan kaçınmak için Pattern.DOTALL bayrağını kullanmanız gerektiğini belirtmek gerekir.
— cletus

Yukarıdaki kalıbı kullanarak, BAR dizesini içeren dizeyi çıkarmak için bunu nasıl kullanırsınız? Pattern API'sına ve Matcher API'sine bakıyorum ancak dizenin kendisini nasıl alacağından hala emin değilim.
— digiarnie

@cletus: İyi çağrı! @digiarnie: Cevaba maç için saman adam kodu içeren bir düzeltme ekledim.
— Bryan Kyle

30

normal olmayan yol:

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

alternatif olarak, biraz daha iyi performans / bellek kullanımı için (teşekkürler Hosam):

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

1
Bunun lastIndexOf(']')yerine iç içe parantezleri işleyecekti. Ayrıca, kullanmaktan indexOf(char)daha hızlı olacağına inanıyorum indexOf(String).
— Hosam Aly

Rica ederim. Performansla ilgili notunuz da çok önemlidir, çünkü lastIndexOfkapanış braketini bulmak kesinlikle daha hızlı olacaktır.
— Hosam Aly

3
daha hızlı, substring vb dizin veya regexp nedir?
— Toskan

2
Amit'in aşağıdaki "alıntılanan" değeri konusuna bakın: input.indexOf ('[') + 1
— gcbound

28

Bu çalışan bir örnektir:

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

Görüntüleniyor :

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

Eğer aralarında ne varsa almanız gerekiyorsa [], şöyle kullanabilirsiniz \[([^\]]*)\]:

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

Formda olması gerekiyorsa identifier + [ + content + ], içeriği yalnızca tanımlayıcı alfasayısal olduğunda ayıklamayı sınırlayabilirsiniz:

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

Bu gibi şeyleri doğrular Foo [Bar]veya myDevice_123["input"]mesela.

Ana mesele

Ana sorun, böyle bir şeyin içeriğini çıkarmak istediğinizde:

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

Regex çalışmaz ve dönecektir BAR[CAT[123ve FOO.
Regex'i şu şekilde değiştirirsek, \[(.*)\]biz iyiyiz, ancak sonra, içeriği daha karmaşık şeylerden çıkarmaya çalışıyorsanız:

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

Hiçbir Regex çalışmaz.

Her durumda doğru içeriği çıkarmak için en doğru Regex, []çiftleri dengelemek ve size içerik vermek zorunda kalacağı için çok daha karmaşık olacaktır .

Daha basit bir çözüm

Sorunlarınız karmaşıklaşıyor ve []keyfi içerik varsa, bunun yerine çiftleri dengeleyebilir ve []Regex'ten daha eski düz bir kod rat kullanarak dizeyi ayıklayabilirsiniz:

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

Bu gerçek koddan daha sözde kod, ben bir Java kodlayıcı değilim bu yüzden sözdiziminin doğru olup olmadığını bilmiyorum, ama üzerinde geliştirmek kolay olmalıdır.
Önemli olan bu kodun çalışması ve ne kadar []karmaşık olsa da içeriğini çıkarmanıza izin vermesidir .


2

Bence düzenli ifadeniz şöyle görünecektir:

/FOO\[(.+)\]/

FOO'nun sabit olacağını varsayarsak.

Bunu Java'ya koymak için:

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

FOO [BAR] FOO [BAZ] -> normal
— ifadenizle

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

Bu, ilk '[' ve son ']' arasındaki değeri döndürür

Foo [Bar] => Bar

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

Not: Giriş dizesi iyi biçimlendirilmemişse hata denetimi eklemelisiniz.


0

içinde başka kapanış köşeli ayraca izin verilmediğini varsayarsak, / FOO \ [([^ \]] *) \] /


0

Ben arasına olmayan] karakter maksimum sayıda istediğinizi tanımlarsınız [ve ]. Bunların ters eğik çizgilerden kaçması gerekir (ve Java'da bunların tekrar kaçması gerekir) ve non-] tanımlaması bir karakter sınıfıdır, dolayısıyla içeride [ve ](yani [^\\]]). Sonuç:

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

0

MYearInDB.toString () = [2013] 'den gelen bazı dizeleri ayrıştırmak istiyorsanız, bu şekilde çalışması 2013'ü verecektir.

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

Bu normal ifade benim için çalışıyor:

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

misal:

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

çıktı:

Match 1
1.  company_details
Match 2
1.  company_details

Http://rubular.com/ adresinde test edilmiştir.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.