2011-07-03 13 views
59

Mam plik z niestandardowymi znacznikami i chciałbym napisać wyrażenie regularne, aby wyodrębnić ciąg znaków między tagami. Na przykład jeśli znacznik jest:Wywołanie języka Java w celu wyodrębnienia tekstu między tagami

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

Jak napisać wyrażenie regularne wyodrębnić tylko ciąg pomiędzy znacznikami. Ten kod wydaje się być krokiem we właściwym kierunku:

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

Nie jestem pewien, co dalej. Jakieś pomysły? Dzięki.

+1

Na początek, trzeba uciec '[]' nawiasów kwadratowych, które są metaznakami w regex. – ridgerunner

Odpowiedz

127

Jesteś na dobrej drodze. Teraz po prostu trzeba wyodrębnić żądaną grupę, w następujący sposób:

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)); // Prints String I want to extract 

Jeśli chcesz wyodrębnić wiele hitów, spróbuj tego:

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

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

Jednak zgadzam się, że wyrażenia regularne nie są najlepszą odpowiedzią tutaj. Użyłbym XPath do znalezienia elementów, które mnie interesują. Aby uzyskać więcej informacji, zobacz The Java XPath API.

+3

Dziękuję bardzo, właśnie tego potrzebowałem. Zajrzę do XPath, ale na razie myślę, że to rozwiązanie zadziała. Moje aplikacje są bardzo proste i prawdopodobnie pozostaną w ten sposób. Dzięki jeszcze raz! – b10hazard

+0

Dzięki, zadziałało !! – Imran

+0

dzięki, naprawdę pomogło –

1

Przedrostkiem tej odpowiedzi jest "nie powinieneś używać wyrażeń regularnych do parsowania XML - spowoduje to tylko przypadki brzegowe, które nie działają poprawnie, i regex na zawsze zwiększający złożoność, podczas gdy spróbuj to naprawić. "

Mając na uwadze powyższe, należy postępować dopasowując ciąg i chwytając grupę, którą chcesz:

if (m.matches()) 
{ 
    String result = m.group(1); 
    // do something with result 
} 
9

Aby być dość rzetelny, wyrażenia regularne nie są najlepszym pomysłem dla tego typu analizy składniowej. Wyrażone wyrażenie regularne prawdopodobnie zadziała dobrze w prostych przypadkach, ale jeśli sytuacja stanie się bardziej skomplikowana, pojawią się ogromne problemy (ten sam powód, dla którego nie można rzetelnie parsować HTML za pomocą wyrażeń regularnych). Wiem, że pewnie nie chcesz tego słyszeć, wiem, że nie, gdy zadawałem ten sam typ pytań, ale parsowanie ciągów stało się bardziej wiarygodne dla mnie po tym, jak przestałem próbować używać wyrażeń regularnych do wszystkiego.

jTopas to NIESAMOWITY tokenizer, który ułatwia ręczne pisanie analizatorów składni (SILNIE sugeruję jtopas za pomocą standardowych bibliotek java/etc). Jeśli chcesz zobaczyć jtopas w działaniu, here kilka Parsery pisałem używając jTopas do analizowania this typ pliku

Jeśli parsowania plików XML, należy używać biblioteki parsera XML.Nie zrobić mu poczuć, chyba że są po prostu robi to dla zabawy, istnieje wiele lokali sprawdzonych opcji tam

+0

Dzięki za sugestię. Dodałem do nich zakładki i na pewno zajrzę się wykorzystaniem tego w przyszłych projektach. Na razie metoda regex jest prawdopodobnie tą, z którą będę korzystał, ponieważ plik, który analizuję jest bardzo mały/prosty. – b10hazard

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

rodzajowe, prostsze i nieco prymitywne podejście do znalezienia etykiety, atrybutu i wartość

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

Spróbuj tego:

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

Na przykład:

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

wyjściowa:

10 Ene

3,08%

0
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++; 
     } 
Powiązane problemy