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.