Etiketler arasında metin ayıklamak için Java normal ifadesi


82

Bazı özel etiketlere sahip bir dosyam var ve dizeyi etiketler arasında çıkarmak için normal bir ifade yazmak istiyorum. Örneğin, etiketim:

[customtag]String I want to extract[/customtag]

Yalnızca etiketler arasındaki dizeyi çıkarmak için nasıl bir normal ifade yazardım. Bu kod, doğru yönde atılmış bir adım gibi görünüyor:

Pattern p = Pattern.compile("[customtag](.+?)[/customtag]");
Matcher m = p.matcher("[customtag]String I want to extract[/customtag]");

Bundan sonra ne yapacağından emin değilim. Herhangi bir fikir? Teşekkürler.


1
Yeni başlayanlar için, []bir normal ifadede meta karakter olan köşeli parantezlerden kaçınmanız gerekir.
ridgerunner

Yanıtlar:


186

Doğru yoldasın. Şimdi, aşağıdaki gibi istediğiniz grubu çıkarmanız yeterlidir:

final Pattern pattern = Pattern.compile("<tag>(.+?)</tag>", Pattern.DOTALL);
final Matcher matcher = pattern.matcher("<tag>String I want to extract</tag>");
matcher.find();
System.out.println(matcher.group(1)); // Prints String I want to extract

Birden fazla isabet çıkarmak istiyorsanız, şunu deneyin:

public static void main(String[] args) {
    final String str = "<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear</tag>";
    System.out.println(Arrays.toString(getTagValues(str).toArray())); // Prints [apple, orange, pear]
}

private static final Pattern TAG_REGEX = Pattern.compile("<tag>(.+?)</tag>", Pattern.DOTALL);

private static List<String> getTagValues(final String str) {
    final List<String> tagValues = new ArrayList<String>();
    final Matcher matcher = TAG_REGEX.matcher(str);
    while (matcher.find()) {
        tagValues.add(matcher.group(1));
    }
    return tagValues;
}

Bununla birlikte, burada normal ifadelerin en iyi yanıt olmadığını kabul ediyorum. İlgilendiğim öğeleri bulmak için XPath kullanırım. Daha fazla bilgi için Java XPath API'ye bakın .


3
Çok teşekkürler, ihtiyacım olan buydu. XPath'leri inceleyeceğim, ancak şimdilik bu çözümün işe yarayacağını düşünüyorum. Uygulamalarım çok basit ve muhtemelen bu şekilde kalacak. Tekrar teşekkürler!
b10hazard

Bu ip ne olacak "<tag>apple</tag><b>hello</b><tag>orange</tag><tag>pear"? pearYakın etiketi olmadan nasıl geçebiliriz ?
K.Sopheak

Genellemek için: private String extractDataFromTags (String tag) {Pattern pattern = Pattern.compile ("<. +?> (. +?) </.+?>"); Eşleştirici eşleştirici = pattern.matcher (etiket); matcher.find (); dönüş (matcher.group (1)); //
Çıkarmak

15

Dürüst olmak gerekirse, bu tür bir çözümleme için düzenli ifadeler en iyi fikir değildir. Gönderdiğiniz normal ifade, muhtemelen basit durumlarda harika çalışacaktır, ancak işler daha karmaşık hale gelirse, büyük sorunlar yaşarsınız (HTML'yi normal ifadelerle güvenilir bir şekilde ayrıştıramamanızın nedeni aynıdır). Muhtemelen bunu duymak istemediğinizi biliyorum, aynı türden soruları sorduğumda istemediğimi biliyorum, ancak her şey için normal ifadeleri kullanmayı bıraktıktan sonra dize ayrıştırma benim için ÇOK daha güvenilir hale geldi.

jTopas , el ile ayrıştırıcıları yazmayı oldukça kolaylaştıran MUHTEŞEM bir belirteçleştiricidir (standart java tarayıcı / vb. kitaplıklar üzerinden ŞİDDETLE jtopaları öneririm). Jtopaları çalışırken görmek istiyorsanız, işte bu tür dosyaları ayrıştırmak için jTopas kullanarak yazdığım bazı ayrıştırıcılar

XML dosyalarını ayrıştırıyorsanız, bir xml ayrıştırıcı kitaplığı kullanmanız gerekir. Bunu sadece eğlence için yapmadığınız sürece kendiniz yapmayın, birçok kanıtlanmış seçenek var


Önerin için teşekkürler. Onları yer imlerine ekledim ve bunu gelecekteki projelerde kullanmayı kesinlikle inceleyeceğim. Şimdilik, ayrıştırdığım dosya çok küçük / basit olduğundan, normal ifade yöntemi muhtemelen benim gideceğim yöntemdir.
b10hazard

7

Etiket, nitelik ve değer bulmak için genel, daha basit ve biraz ilkel bir yaklaşım

    Pattern pattern = Pattern.compile("<(\\w+)( +.+)*>((.*))</\\1>");
    System.out.println(pattern.matcher("<asd> TEST</asd>").find());
    System.out.println(pattern.matcher("<asd TEST</asd>").find());
    System.out.println(pattern.matcher("<asd attr='3'> TEST</asd>").find());
    System.out.println(pattern.matcher("<asd> <x>TEST<x>asd>").find());
    System.out.println("-------");
    Matcher matcher = pattern.matcher("<as x> TEST</as>");
    if (matcher.find()) {
        for (int i = 0; i <= matcher.groupCount(); i++) {
            System.out.println(i + ":" + matcher.group(i));
        }
    }

Gibi farklı etiketlerle veya iç içe etiketlerin bir dizi varsa desen ne olurdu <h2>Mac</h2><h1>loves it</h1>ya <h2>Mac<h1>liked your answer</h1></h2>?
MAC

1
lütfen düzenleyin i <matcher.groupCount (); i <= matcher.groupCount (); ilk eşleşen alt dizeyi dahil etmek için örn. 0'ıncı dizinde
AVA

4

Bunu dene:

Pattern p = Pattern.compile(?<=\\<(any_tag)\\>)(\\s*.*\\s*)(?=\\<\\/(any_tag)\\>);
Matcher m = p.matcher(anyString);

Örneğin:

String str = "<TR> <TD>1Q Ene</TD> <TD>3.08%</TD> </TR>";
Pattern p = Pattern.compile("(?<=\\<TD\\>)(\\s*.*\\s*)(?=\\<\\/TD\\>)");
Matcher m = p.matcher(str);
while(m.find()){
   Log.e("Regex"," Regex result: " + m.group())       
}

Çıktı:

10 Ene

% 3.08


2
    final Pattern pattern = Pattern.compile("tag\\](.+?)\\[/tag");
    final Matcher matcher = pattern.matcher("[tag]String I want to extract[/tag]");
    matcher.find();
    System.out.println(matcher.group(1));

etiket için ön ek hakkında (önek
dinamikse

2
    String s = "<B><G>Test</G></B><C>Test1</C>";

    String pattern ="\\<(.+)\\>([^\\<\\>]+)\\<\\/\\1\\>";

       int count = 0;

        Pattern p = Pattern.compile(pattern);
        Matcher m =  p.matcher(s);
        while(m.find())
        {
            System.out.println(m.group(2));
            count++;
        }

1

Bu yanıtın önüne "XML'i ayrıştırmak için normal bir ifade kullanmamalısınız - bu yalnızca doğru çalışmayan uç durumlarla ve siz onu düzeltmeye çalışırken karmaşıklığı sonsuza kadar artan bir normal ifadeyle sonuçlanacaktır. . "

Bununla birlikte, dizeyi eşleştirerek ve istediğiniz grubu alarak ilerlemeniz gerekir:

if (m.matches())
{
   String result = m.group(1);
   // do something with result
}
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.