kostenloser Webspace werbefrei: lima-city


Regulärer Ausdruck - Schlüsselwertpaar

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    silecom

    silecom hat kostenlosen Webspace.

    Hi,
    ich sitz jetzt schon eine halbe Ewigkeit daran und schaff es mit RegEx einfach nicht, meine Frage jetzt ob das so überhaupt funktioniert wie ich es mir gedacht habe...

    Als zu durchsuchender bzw. zu ersetzender String dient mir der Folgende:
    '"a" = "b", "d" = 55.1, c="x", x=5'


    Für jeden Beistrich der so ein Wertpaar trennt möchte ich nun ne zufällige Zahl einfügen, sprich diesen ersetzen. Es gibt aber die Möglichkeit den Beistrich im Schlüssel als auch im Wert zu definieren (nur wenn der jeweilige Teil im Hochkomma ist). Siehe:

    "a,b" = "x,y" // +
    a53k = 53.32 // +
    54k = 43.23 // - weil der Schlüssel mit einer Zahl beginnt
    a,b = "x,y" // -
    "a,b" = x,y // -


    Nun zum wichtigsten aller Dinge, der reguläre Ausdruck.

    Für den Schlüssel habe ich
    ("[\S]+"|[a-z]{1}[a-z0-9_]*)
    vorgesehen.
    Bei der Zuweisung können sowohl links und rechts vom = Leerzeichen, Tabs oder sonst was sein:
    [\s]*=[\s]*
    und dann noch der Wert inklusive Beistrich
    (".+"|[0-9]+\.?[0-9]*)[\s]*,
    .

    Ergibt:

    '("[\S]+"|[a-z]{1}[a-z0-9_]*)[\s]*=[\s]*(".+"|[0-9]+\.?[0-9]*)[\s]*,'


    Mir ist klar dass ich hier am Ende eines solchen Paares den Beistrich voraussetze, was aber erstmal egal sein sollte.

    Was funktioniert jetzt nicht?

    Solang ich als Wert eine Zahl nimm ersetzt er den Beistrich korrekt, wenn ich jetzt aber als Wert einen String definiere, wird der Beistrich ignoriert.

    Falsch:
    Eingabe: '"a" = "b", "d" = 55.1, c="x", x=5'
    Ergebnis falsch: "a"="b", "d" = 55.1, c="x"ERSETZT x=5ERSETZT
    Ergebnis richtig: "a"="b"ERSETZT "d" = 55.1ERSETZT c="x"ERSETZT x=5ERSETZT


    Eingabe: '"a" = 421, "d" = 55.1, c=12, x=5'
    Ergebnis richtig: "a"=421ERSETZT "d"=55.1ERSETZT c=12ERSETZT x=5ERSETZT


    Würd mich freuen wenn sich einer kurz die Zeit nimmt, danke.
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Ich habe mich ein wenig in das Thema eingelesen, ist ja nicht ganz so einfach.

    Ich würde versuchen, den im Schlüssel vorgegebenen Non-Whitespace ([\S]) durch den im Wert benutzen Ausdruck für ein beliebiges Zeichen (.+) zu ersetzen. Es könnte nämlich sein, dass das je nach Version usw. (hier kenne ich mich nicht genau aus) nicht implementiert ist, und daher der Non-Whitespace nicht erkannt werden kann.

    So sollte der Ausdruck dann aussehen:

    '(".+"|[a-z]{1}[a-z0-9_]*)[\s]*=[\s]*(".+"|[0-9]+\.?[0-9]*)[\s]*,'


    Ich hoffe das hilft, wenn nicht befasse ich mich gerne weiter mit dem Thema.

    Gruß,
    Markus
  4. Autor dieses Themas

    silecom

    silecom hat kostenlosen Webspace.

    Die Unterstützung von dem \S ist schon gegeben, aber ich zweifle schon selbst an einer möglichen Lösung mit RegEx.

    Ich hab deshalb das ganze mit einer Schleife versucht zu realisieren. War den Aufwand zwar für meine Zwecke jetzt überhaupt nicht wert aber ja. Das große Problem was es jetzt gibt ist die Abgrenzung von Wert und Schlüssel.

    Eingaben wie
    "x"=4215.1231, j321="4891020000"4     12u49''"''!"§"''%!"§$"$§"&/ESYSF"
    funktionieren.
    Aber wenn jetzt beispielsweise
    "x"="="y"
    dasteht, dann wirft mein "Parser" einen Fehler, weil er glaubt dass als Schlüssel jetzt "x" dient und nicht "x"=".

    Für mich verständlich dass der Fehler kommt, aber ich habe keine Ahnung wie ich hier zu einer Lösung komme.

    Sicher kann ich = und , in Wert und Schlüssel verbieten, aber das ist nicht mein Ziel da man als Wert schnell einen Satz mit ein zwei Beistrichen und den dazugehörigen Delimitern verwenden kann. Die Kombination aus Delimiter und = oder , bereitet mir Sorgen :(

    Vllt. weiss einer von euch mehr.

    Beitrag zuletzt geändert: 28.7.2009 22:48:46 von silecom
  5. c****s

    silecom schrieb:

    Aber wenn jetzt beispielsweise
    "x"="="y"
    dasteht, dann wirft mein "Parser" einen Fehler, weil er glaubt dass als Schlüssel jetzt "x" dient und nicht "x"=".

    Für mich verständlich dass der Fehler kommt, aber ich habe keine Ahnung wie ich hier zu einer Lösung komme.


    Der Parser macht das ja richtig. Der L-Value von deinem Beispiel ist ja auch "x" und nicht "x"=". Das Problem hierbei ist aber nicht das = im String, sondern die Anführungszeichen. Wenn du Anführungszeichen in deinen Strings erlauben willst, musst du dir irgendeinen Escapecharacter aussuchen (gängigerweiße Backslash) um diese "unfunktional" zu machen.

    EDIT:

    Und so funktioniert's: Du darfst innerhalb der Strings keine Hochkommata zulassen: Die Regex lautet also:

    ("[\S&&[^"]]+"|[a-z]{1}[a-z0-9_]*)[\s]*=[\s]*("[\S&&[^"]]+"|[0-9]+\.?[0-9]*)[\s]*,"


    Beispiel:
    public class Main
    {
    	public static void main (String [] args)
    	{
    		Pattern p = Pattern.compile ("(\"[\\S&&[^\"]]+\"|[a-z]{1}[a-z0-9_]*)[\\s]*=[\\s]*(\"[\\S&&[^\"]]+\"|[0-9]+\\.?[0-9]*)[\\s]*,");
    		Matcher m = p.matcher ("\"a\" = \"b\", \"d\" = 55.1, c=\"x\", x=5,");
    		System.out.println  (m.replaceAll ("$1=$2ERSETZT") );
    	}
    }


    Das macht folgende Ausgabe:

    "a"="b"ERSETZT "d"=55.1ERSETZT c="x"ERSETZT x=5ERSETZT


    Dasselbe Programm liefert folgende Ausgabe:
    Input: "x,y" = "b", "d" = "y,x", c="x", x=5,
    Output: "x,y"="b"ERSETZT "d"="y,x"ERSETZT c="x"ERSETZT x=5ERSETZT


    Edit 2:
    Warum lässt du im String keine Leerzeichen zu? Die tun ja keinem weh und mach die Regex einfacher:
    ("[^"]+"|[a-z]{1}[a-z0-9_]*)[\s]*=[\s]*("[^"]+"|[0-9]+\.?[0-9]*)[\s]*,


    Beitrag zuletzt geändert: 28.7.2009 23:38:06 von census
  6. Autor dieses Themas

    silecom

    silecom hat kostenlosen Webspace.

    Leerzeichen in Werte werden zugelassen, in Schlüssel aber nicht, das soll aber so sein.

    Wie ich eh geschrieben hab ist es klar wieso da ein Fehler kommt, es läuft eh korrekt ab, nur lösteben dieses " den Fehler aus und die Vorgangsweise wie ich den String durchnehme.

    Ich wills mit dem RegEx auch gar nicht weitermachen weil das mit dem meines Erachtens viel zu kompliziert werden würde.

    Aber danke für den Dankanstoß, ließe sich das auch noch anders ändern?
  7. c****s

    Warum zu kompliziert? Die Regex schreibt man nur einmal und danach macht dein Matcher den Rest der Arbeit.

    Die Regex
    ("[\S&&[^"]]+"|[a-z]{1}[a-z0-9_]*)[\s]*=[\s]*("[\S&&[^"]]+"|[0-9]+\.?[0-9]*)[\s]*,

    ist doch sehr komfortabel. . .

    Wenn du ein match_all (oder wie auch immer das in deiner API heißen mag) dann über eine Zeichenkette laufen läßt, schmeißt dir die Regex alle Wertepärchen raus (jetzt auch richtig mit Namen in Hochkommata) und in der ersten Capturing Group steht der Schlüssel und in der zweiten Capturing Group der Wert. Das ist doch sehr komfortabel.

    Anders lösen? Ja, mit Hand zu Fuß. Also grob gesagt, das Rad neu erfinden und selbst matchen.
  8. Autor dieses Themas

    silecom

    silecom hat kostenlosen Webspace.

    Ok, danke für deine Hilfe, jetzt weiss ich wo ich steh.

    Eine Frage hätte ich da noch. Ist es üblich dass Programmiersprachen für Funktionen die Möglichkeit bieten beliebig viele Parameter in einem Array oder so zu übergeben? Ich denke da jetzt an dein Beispiel mit args oder so.

    Beispiel. Du hast eine Funktion x(param) mit dem einen Parameter.
    Der Aufruf erfolgt durch x(param1, param2)

  9. c****s

    Eine variable Parameterliste können nicht alle Sprachen. C zum Beispiel kann es und die Deklarationen sehen dann wie folgt aus:

    void printf (const char* format, ...);
    int sum (int count, ...);


    Java kann das auch und das sieht so aus:

    public int sum (int ... args);


    Falls eine Sprache das nicht kann, so ist es bei den meisten doch möglich einen Array zu übergeben und in den kannst du ja dann soviel reinpacken wie du willst:

    public int sum (int [] args);
  10. Autor dieses Themas

    silecom

    silecom hat kostenlosen Webspace.

    So nach ein paar Recherchen bin ich wieder auf einen Ausdruck gestoßen der mir irgendwie Sorgen bereitet.

    Was ist der Unterschied zwischen (.*) und (.*?) ?

    Beim ersten ist es ein beliebiges Zeichen was beliebig oft, auch keinmal vorkommen kann. Beim zweiten kann ich für mich nur dasselbe erkennen. Aber es gibt andere Ergebnisse.

    ".*?"


    Beispiel: " klf" "fjkammdan

    Der obige Code liefert " klf"
    ohne dem Fragezeichen aber " klf" "

    Ich verstehs nicht warum. Das einzige was ich mir so vorstellen kann ist dass die beliebigen Zeichen bis zum ersten " gehen und der Teil somit abgeschlossen ist.

    PS: Hat nicht direkt was mit dem Threadthema zu tun, würde mich nur interessieren.

    Beitrag zuletzt geändert: 31.7.2009 21:02:48 von silecom
  11. silecom schrieb:
    So nach ein paar Recherchen bin ich wieder auf einen Ausdruck gestoßen der mir irgendwie Sorgen bereitet.



    .
    entspricht einen beliebige Zeichen, ausser Newline (\n)

    ? : Der voranstehende Ausdruck ist optional, er kann einmal vorkommen, muss es aber nicht, d. h. der Ausdruck kommt null- oder einmal vor. (Dies entspricht {0,1} )

    * : Der voranstehende Ausdruck darf beliebig oft (auch keinmal) vorkommen. (Dies entspricht {0,} )


    Ich kann Dein Beschriebenes verhalten nicht (ganz) nachvollziehen in beiden fällen liefert mir preg_match_all() alles, nur mit dem Unterschied das /.*/ als ersten treffer gleich Alles hat und mit Fragezeichen immer nur einen Buchstaben.

    Ich vermute mal das das Fragezeichen sozusagen den Stern als Quantoren für den Punkt überschreibt.
    Anders ausgedrückt aus /.*?/ macht php /.?/

    um mein Ergebnis zu verdeutlichen poste ich mal die Ergebnis-Arrays:
    preg_match_all('/.*/',' " klf" "fjkammdan', $array);
    http://www.regex-tester.de/uc_708_de.html

    Array
    (
    [0] => Array
    (
    [0] => " klf" "fjkammdan
    [1] =>
    )

    )



    preg_match_all('/.*?/',' " klf" "fjkammdan', $array);
    http://www.regex-tester.de/uc_705_de.html

    Array
    (
    [0] => Array
    (
    [0] =>
    [1] => "
    [2] =>
    [3] =>
    [4] =>
    [5] => k
    [6] =>
    [7] => l
    [8] =>
    [9] => f
    [10] =>
    [11] => "
    [12] =>
    [13] =>
    [14] =>
    [15] => "
    [16] =>
    [17] => f
    [18] =>
    [19] => j
    [20] =>
    [21] => k
    [22] =>
    [23] => a
    [24] =>
    [25] => m
    [26] =>
    [27] => m
    [28] =>
    [29] => d
    [30] =>
    [31] => a
    [32] =>
    [33] => n
    [34] =>
    )

    )




    Beitrag zuletzt geändert: 1.8.2009 12:31:08 von simuliertes
  12. c****s

    Obacht simuliertes, "a little knowing is a dangerous thing." Deine Vermutungen sind zwar schön, aber leider falsch.

    Bei Regex gibt es drei Arten des Matchens: Greedy, reluctant und possessive.

    Der Unterschied zwischen * und *? ist, dass ersteres greedy ist und zweiteres reluctant.

    cf. http://javascript.about.com/library/blre09.htm

    Das erklärt auch das Verhalten, das silecom beschrieben hat:
    ".*?"  =>  " klf" "fjkammdan

    Liefert den kürzesten Treffer zurück, da es reluctant ist, also
    " klf"


    ".*"  =>  " klf" "fjkammdan

    Liefert den längsten Treffer zurück, da es greedy ist, also
    " klf" "


    Beitrag zuletzt geändert: 1.8.2009 12:59:48 von census
  13. census schrieb:
    Obacht simuliertes, "a little knowing is a dangerous thing." Deine Vermutungen sind zwar schön, aber leider falsch.


    verdammt, schon wieder ^^

    Aber das ich nur vermutet habe hatte ich ja erwähnt.
    Wieso kommt es aber das ich ein komplett anderes Ergebnis habe? (nämlich den vollen string " klf" "fjkammdan oder nur einen Buchstaben)



    Beitrag zuletzt geändert: 1.8.2009 13:16:15 von simuliertes
  14. c****s

    Weil du nicht auf
    ".*" oder ".*?"

    matchst sondern auf
    .* oder .*?


    Beitrag zuletzt geändert: 1.8.2009 13:19:04 von census
  15. Autor dieses Themas

    silecom

    silecom hat kostenlosen Webspace.

    Super, danke für die Antworten, werde mir die Seite mal ansehen.
  16. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!