Nach regex splitten

Status
Nicht offen für weitere Antworten.

thE_29

Top Contributor
Hiho!

Ich möchte einen String nach , (Beistrich) splitten, aber wenn der Beistrich zwischen 2 Anführungszeichen steht dann nicht!

Bsp.: String = getBla(), "hier ist ein, du schelm du", getOberbla()

Wenn ich das jetzt splitte will ich das haben:

[0] = getBla()
[1] = "hier ist ein, du schelm du"
[2] = getOberBla()



Ich weiß (bzw glaube 😉) dass man das via regex machen kann. Aber wie weiß ich nicht...


mfg
 
Hilft mir leider auch nicht weiter..

Da 1. dort viel auf den Scanner eingegangen wird, ich aber mit 1.4.2 arbeite und 2. kaum was von regex erwähnt wird!
 
Das du bisher nur auf allgemeine Infos zu RegExps verwiesen wurdest,
deutet darauf hin, daß es nicht geht. Denn ich bin mir sicher,
daß einige der hiesigen RegExperten sich sich bereits ohne Erfolg bemüht haben
eine Lösung zu finden (die lassen ja sonst nicht so lange auf sich warten :wink: )

Mein Bauchgefühl (früher mal antrainiert) sagt mir, daß es keine
derartige RepExp geben kann (Mächtigkeit von Typ-3-Grammatiken und
der ganze Kram).

Beweisen kann ich das jetzt aber nicht (mehr). 😳
 
Mein Bauchgefühl sagt es geht.
Mehr hab ich leider auch nicht zu bieten...

Dein Beispiel ist etwas verwirrend, vielleicht hat deswegen noch niemand ne Lösung..
Sieht aus als würdest du Funktionen verwenden, aber nach genauerer Betrachtung vermute ich du meinst das alles als Zeichenkette..

Bsp in Java-Syntax: "getBla(), \"hier ist ein, du schelm du\", getOberbla()" !?
 
Eigentlich gehts darum, nen Java Source zu durchsuchen und Einträge in die Datenbank zu schreiben!

Die 3 Parameter sind bei einer Methode angegeben und ich wollte sie nach , splitten!

Problem ist halt das, wenn etwas unter " " steht, dürfte er das net splitten!
 
Bei derartigen Aufgabenstellungen schreibst du dir am besten deinen eigenen kleinen Parser.
Pseudocode:

Code:
int last = 0;
int pos = -1;
boolean inString = false;
while (++pos < source.length()) {
  char c = source.charAt(pos);
  switch (c) {
    case '"' : inString = !inString; break;
    case ',' : 
      if (!inString) {
        newToken(source, last, pos);
        last = pos+1;
      }
      break;
    default: break;
}
if (!inString)
  newToken(source, last, pos-1) // oder so ähnlich
 
Soll es allgemeingültig werden? Dann musst du auch auf Kommentare achten, bsp:

Code:
getBla(), /* hmm, so ein Mist!!*/ "hier ist ein, du schelm du", getOberbla()  //hier gibt es Kommas,,,

Und vergiss ',' nicht.
 
Also ich denke schon, daß sich das mit einem Regex lösen lässt. Das Splitten klappt schon, aber die Quotings werden noch verschluckt:

Code:
Pattern p   =  Pattern.compile("([^\"]*),([^\"]*)");
Matcher m = p.matcher(in);
while (m.find())
{
      System.out.println(">> " +  m.group());
}

Sysout:
Code:
>> getBla(),  
>> hier ist ein, du schelm du
>> , getOberbla()

Ich habe auch etwas mit Look-Aheads und Look-Behinds experimentiert, aber bisher ohne Erfolg :-(
 
Naja, die Quotes wären net so wichtig!
Kommentare sind auch keine Vorhanden (also dazwischen)
Und den einen Beistrich könnte ich auch wegmachen..

Naja, danke erstmals, ich guck morgen weiter!
 
foobar hat gesagt.:
Also ich denke schon, daß sich das mit einem Regex lösen lässt.

Optimist! 😎

Was liefert deine RegExp denn bei Auswertung der Parameter von

Code:
System.out.println("Achtung: ", "ich bin ein \"String\", 'ich nicht'", 42);
 
Es sieht immer so aus

Bundle.getULabel("KEY_WORD_OHNE_BEISTRICH",getLanguage(),"Deutscher default Text, mit Beistrichen");

Es kann hinten noch was stehen, aber das interessiert mich nicht! (Bsp.: ..., "default text, mit Beistrichen", new String[]{"param1","param2"}); )

Ziel ist es, einen Wrapper zu schreiben der mir die Keywörter + defaulttext in eine Datenbank schreibt!

Ansonsten muss ich ziemlich viel mit Hand nachtipseln 🙁
 
Leroy42 hat gesagt.:
foobar hat gesagt.:
Also ich denke schon, daß sich das mit einem Regex lösen lässt.

Optimist! 😎

Was liefert deine RegExp denn bei Auswertung der Parameter von

Code:
System.out.println("Achtung: ", "ich bin ein \"String\", 'ich nicht'", 42);

Code:
>> , 
>> , 'ich nicht''', 42);
 
thE_29 hat gesagt.:
Es sieht immer so aus

Bundle.getULabel("KEY_WORD_OHNE_BEISTRICH",getLanguage(),"Deutscher default Text, mit Beistrichen");

Es kann hinten noch was stehen, aber das interessiert mich nicht! (Bsp.: ..., "default text, mit Beistrichen", new String[]{"param1","param2"}); )

Also dieses Muster läßt sich mit folgendem Regulären Ausdruck zerlegen:

Code:
    String input =
        "Bundle.getULabel(\"keyword\",getLanguage(),\"Text, sogar mit Komma\");\n" +
        "Bundle.getULabel(\"another_keyword\",getLanguage(),\"Hier ein Text ohne Komma\");\n" +
        "Bundle.getULabel(\"third_keyword\",getLanguage(),\"Und hier mit Zusatzinformationen -->\", new String[]{\"param1\",\"param2\"});";

    String pattern = "Bundle[.]getULabel\\(\"" +
        // [1] = Schlüsselwort
        "([^\"]*?)\"," +
        // [2] = getLanguage
        "([^,]*?),\"" +
        // [3] = Text
        "([^\"]*?)\".*?\\);";
		
    Pattern p = Pattern.compile(pattern);
    Matcher m = p.matcher(input);

    while (m.find()) {
        System.out.println("[1]=" + m.group(1));
        System.out.println("[2]=" + m.group(2));
        System.out.println("[3]=" + m.group(3));
        System.out.println("---");
    }

Ausgabe:
Code:
[1]=keyword
[2]=getLanguage()
[3]=Text, sogar mit Komma
---
[1]=another_keyword
[2]=getLanguage()
[3]=Hier ein Text ohne Komma
---
[1]=third_keyword
[2]=getLanguage()
[3]=Und hier mit Zusatzinformationen -->
---

Dürfen aber nirgends Leerzeichen drin sein, also vorher evtl. rausfiltern!
 
Hhm, hast Recht, da hab ich so leichtfertig geschrieben vorher alle Leerzeichen rausfiltern, aber mit replaceAll("[ ]", "") bspw. würde man ja auch die Leerzeichen in den Zeichenketten wegfiltern.

Also hier noch mal eine modifizierte Version, die beliebig viele Whitespace-Zeichen an den Java-üblichen Stellen erlaubt:

Code:
    String input =
        "  Bundle.getULabel(\"keyword\",getLanguage() , \"Text, sogar mit Komma\") ;  \n" +
        "Bundle.getULabel  ( \"another_keyword\",   getLanguage(),  \"Hier ein Text ohne Komma\")  ;\n" +
        "\tBundle.getULabel(\"third_keyword\",\t  getLanguage()   , \"Und hier mit Zusatzinformationen -->\", new String[]{\"param1\",\"param2\"});";

    String pattern = "Bundle[.]getULabel\\s*\\(\\s*\"" +
        "([^\"]*?)\"\\s*,\\s*" +
        "([^,]*?)\\s*,\\s*\"" +
        "([^\"]*?)\".*?\\)\\s*;";

Liefert die gleiche Ausgabe wie im letzten Beispiel.
 
Na ich erklär mal die einzelnen Teile kurz und knapp:

Code:
String pattern =
    "Bundle[.]getULabel" +  // Den String "Bundle.getULabel" finden
    "\\s*" +  // Eine möglichst lange Sequenz nur aus Whitespace-Zeichen
    "\\(\\s*" +  // Klammer auf und Whitespace-Sequenz
    "\"([^\"]*?)\"" +  // 1. Gruppe (zwischen zwei Anführungszeichen): Sequenz aus beliebigen Zeichen, außer dem Hochkomma
    "\\s*,\\s*" +  // Zwei Whitespace-Sequenzen, getrennt durch ein Komma
    "([^,]*?)" +  // 2. Gruppe: Sequenz aus beliebigen Zeichen, außer Komma
    "\\s*,\\s*" +
    "\"([^\"]*?)\"" +  // 3. Gruppe (wie Gruppe 1)
    ".*?\\)\\s*;";  // Sequenz von beliebigen Zeichen, Klammer zu, Whitespace-Sequenz, Semikolon

Im Text wird nach einer Stelle gesucht, auf die der gesamte RegEx paßt. Mittels Matcher.group(i) kann dann der Text der einzelnen Gruppen (im RegEx durch runde Klammern gekennzeichnet) separat abgefragt werden.

Steht aber alles in der API ... :meld:
 
PyroPi hat gesagt.:
Steht aber alles in der API ... :meld:

Naja, irgendwo finde ich auch Beschreibungen wie ich Schraubenschlüssel
und dergleichen benutze, dann kann ich aber noch lange kein Motor
auseinander und zusammen bauen 😎

Fremde RegExps zu lesen und zu verstehen ist wirklich keine leichte Aufgabe. ???:L
 
Status
Nicht offen für weitere Antworten.

Neue Themen


Zurück
Oben