Seite 1 von 2

Verfasst: Mittwoch 9. Juli 2008, 15:31
von EnTeQuAk
Karl hat geschrieben:EnTeQuAk: Deine Lösung kann aber zum Beispiel nicht mit einem = in einem String umgehen, weil dann ein SyntaxError kommen müsste.
Außerdem wird ja immer gegen eval gepredigt :)
Stimmt, das hier geht aber:

Code: Alles auswählen


def split(s):
    keys = [k for k in s if s[s.index(k)+1]=='=']
    for i, item in enumerate(s):
        if item == '=':
            key = s[i-1]
            if not key in keys:
                continue
            last_key = keys[-1] == key
            if last_key:
                value = s[i+1:]
            else:
                value = s[i+1:s.index(keys[keys.index(key)+1])-1]
            yield key, value

def main():
    ts = u'a=1 b="X =Y Z" c=True d=None'
    print dict((k, eval(v)) for k,v in split(ts))

if __name__ == '__main__':
    main()
Ansonsten sieht Masaru's Lösung auch nicht schlecht aus :D


€dit: Mist, geht auch nicht. Wenn X=Y im `b` value steht, gehts auch nicht. Vergesst die Lösung :D

Shlex Grammatik?

Verfasst: Mittwoch 9. Juli 2008, 15:47
von Kurt Z
Frage: Wie parse ich mit Shlex einen String an der sowohl ' als auch " enthält ? Bzw. wie escape ich Quotes?

Verfasst: Mittwoch 9. Juli 2008, 15:50
von BlackJack
@Kurt Z: Mit einem Backslash.

Verfasst: Mittwoch 9. Juli 2008, 15:53
von Michael Schneider
Hi Masaru,
Masaru hat geschrieben:@Karl: Hier wäre dann das Problem mit einem '=' im String wieder ausgehebelt ;).
Und was ist mit nicht-\w-Zeichen wie [.,;:], Klammern, usw.?

Jens hat bislang noch nicht behauptet (oder ich habe es überlesen), dass es sich um Programmcode oder sogar Python-Code handelt.

Michel

Verfasst: Mittwoch 9. Juli 2008, 15:54
von Masaru
Huch, hab den Seiten-Wechsel gar nicht mitbekommen beim editieren.

Naja, hier mal eine gaaanz kurze Variante

Code: Alles auswählen

import re 
s = u'a=1 b="X=Y=Z" c=True d=None'
r = dict([ (t[0], eval(t[1])) for t in [ h.split('=', 1) for h in re.findall('(\w*=".*"|\w*=\w*)', s) ]])
>>Masaru<<

Verfasst: Mittwoch 9. Juli 2008, 16:02
von Kurt Z
BlackJack hat geschrieben:@Kurt Z: Mit einem Backslash.
wie genau ???

Code: Alles auswählen

>>> shlex.split("""a=1 b='X \' Y Z' c=True d='test' e=None""")
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/lib/python2.3/shlex.py", line 279, in split
    return list(lex)
  File "/usr/lib/python2.3/shlex.py", line 269, in next
    token = self.get_token()
  File "/usr/lib/python2.3/shlex.py", line 96, in get_token
    raw = self.read_token()
  File "/usr/lib/python2.3/shlex.py", line 172, in read_token
    raise ValueError, "No closing quotation"
ValueError: No closing quotation

Verfasst: Mittwoch 9. Juli 2008, 16:09
von BlackJack
@Kurt Z: Ganz einfach mit einem Backslash vor dem entsprechenden Quote. Kleiner Tipp: Du hast da keins weil '\' in Python-Zeichenketten ja auch eine Bedeutung haben.

Code: Alles auswählen

In [101]: print '''foo="X \'Y\' Z"'''
foo="X 'Y' Z"

In [102]: print '''foo="X \\'Y\\' Z"'''
foo="X \'Y\' Z"

Verfasst: Mittwoch 9. Juli 2008, 16:16
von Kurt Z
BlackJack hat geschrieben:@Kurt Z: Ganz einfach mit einem Backslash vor dem entsprechenden Quote. Kleiner Tipp: Du hast da keins weil '\' in Python-Zeichenketten ja auch eine Bedeutung haben.
m.a.W. es geht, aber Python-Code darf nicht die Quelle sein?

Code: Alles auswählen

>>> shlex.split("""a=1 b='X \\' Y Z' c=True d='test' e=None""")
Traceback (most recent call last):
 ...
ValueError: No closing quotation
>>> shlex.split("""a=1 b='X \\\' Y Z' c=True d='test' e=None""")
Traceback (most recent call last):
...
ValueError: No closing quotation
ich kann kein Python bitte zeigts mir...

Verfasst: Mittwoch 9. Juli 2008, 16:41
von Kurt Z
ok so gehts ...

Code: Alles auswählen

>>> shlex.split('a=1 b=" \' \\\" " c=True d="test" e=None')
['a=1', 'b= \' " ', 'c=True', 'd=test', 'e=None']

>>> shlex.split("a=1 b=\" \\\" ' \" c=True d='test' e=None")
['a=1', 'b= " \' ', 'c=True', 'd=test', 'e=None']

Verfasst: Mittwoch 9. Juli 2008, 17:18
von jens
shlex sieht wirklich gut aus! Sehe ich jetzt zum ersten mal... Danke an alle ;)

Verfasst: Donnerstag 10. Juli 2008, 13:22
von jens
Meine Lösung:

Code: Alles auswählen

def make_kwagrs(raw_content):
    """
    convert a string into a dictionary. e.g.:
    
    >>> make_kwagrs('key1="value1" key2="value2"')
    {'key2': 'value2', 'key1': 'value1'}
   
    >>> make_kwagrs('A="B" C=1 D=1.1 E=True F=False G=None')
    {'A': 'B', 'C': 1, 'E': True, 'D': '1.1', 'G': None, 'F': False}
    """
    parts = shlex.split(raw_content)

    result = {}
    for part in parts:
        key, value = part.split("=", 1)
        
        if value in KEYWORD_MAP:
            # True False or None
            value = KEYWORD_MAP[value]
        else:
            # A number?
            try:
                value = int(value)
            except ValueError:
                pass 
                                   
        result[key] = value

    return result
btw. doofes DocTest, siehe: doctest und dict (Key Reihenfolge)

EDIT: Ach, dumm... shlex.split() macht ärger bei unicode:

Code: Alles auswählen

>>> repr(shlex.split(u"A=1 B=2"))
['A\x00\x00\x00=\x00\x00\x001\x00\x00\x00', '\x00\x00\x00B\x00\x00\x00=\x00\x00\x002\x00\x00\x00']

Verfasst: Donnerstag 10. Juli 2008, 15:02
von jens
Ah ich sehe gerade:
Note: The shlex module currently does not support Unicode input.
[mod]shlex[/mod]

Ja, dann... :?

Verfasst: Donnerstag 10. Juli 2008, 15:04
von Karl
Irgendwo muss doch die Herausforderung sein, also los, mach dich ran ;)

Verfasst: Donnerstag 10. Juli 2008, 15:40
von Kurt Z
jens hat geschrieben:Ah ich sehe gerade:
Note: The shlex module currently does not support Unicode input.
[mod]shlex[/mod]

Ja, dann... :?
hmm ...solange du die Grammatik nicht präzisierst, ist jede weitere RegEx Diskussiion sowieso hinfällig...

Kommen in strings quotes vor ?
sowohl ' als auch " ?
Wie soll dann escaped werden ?

Verfasst: Donnerstag 10. Juli 2008, 15:44
von Masaru
Kurt Z hat geschrieben:...Kommen in strings quotes vor ?
sowohl ' als auch " ?
Wie soll dann escaped werden ?
So :)

Code: Alles auswählen

>>> print '\''
'
>>> print """
"

Verfasst: Donnerstag 10. Juli 2008, 15:56
von audax
Das sind 2 Zeilen in PyParsing :o

Verfasst: Donnerstag 10. Juli 2008, 16:00
von Kurt Z
Masaru hat geschrieben: So :)

Code: Alles auswählen

>>> print '\''
'
>>> print """
"
hat er nie präzisiert! Und shlex u/o Python scheinen andere Vorstellungen von escaping zu haben als normale shells wie bash!
>>> print "a=1 b='X \\' Y Z' c=True d='test' e=None"
a=1 b='X \' Y Z' c=True d='test' e=None
>>> shlex.split("a=1 b='X \\' Y Z' c=True d='test' e=None")
Traceback (most recent call last):
File "<stdin>", line 1, in ?
File "/usr/lib/python2.3/shlex.py", line 279, in split
return list(lex)
File "/usr/lib/python2.3/shlex.py", line 269, in next
token = self.get_token()
File "/usr/lib/python2.3/shlex.py", line 96, in get_token
raw = self.read_token()
File "/usr/lib/python2.3/shlex.py", line 172, in read_token
raise ValueError, "No closing quotation"
wie auch immer , ist euch mit ner Perl-RegEx gedient die ihr dann nach Python übersetzt?

Verfasst: Donnerstag 10. Juli 2008, 16:05
von Trundle
Kurt Z hat geschrieben:Und shlex u/o Python scheinen andere Vorstellungen von escaping zu haben als normale shells wie bash!
'\''
funktioniert auch in einer "normalen" Shell nicht.

Verfasst: Donnerstag 10. Juli 2008, 16:14
von Kurt Z
Trundle hat geschrieben:
Kurt Z hat geschrieben:Und shlex u/o Python scheinen andere Vorstellungen von escaping zu haben als normale shells wie bash!
'\''
funktioniert auch in einer "normalen" Shell nicht.
aber es funktioniert in Python, deswegen soll er die Grammatik ja präzisieren!

Code: Alles auswählen

>>> print 'a\'b'
a'b

Verfasst: Donnerstag 10. Juli 2008, 17:56
von jens
Ich habe kein Problem mit quotes. Hab dennoch das eingefügt:

Code: Alles auswählen

value = int(value.strip("'\""))
Aber eigentlich denke ich nicht, das es wirklich wichtig ist.

Hab noch einen Test dazugepackt: http://trac.pylucid.net/changeset/1669