String aufbröseln...

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

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
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"
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

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...
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

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']
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

shlex sieht wirklich gut aus! Sehe ich jetzt zum ersten mal... Danke an alle ;)

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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']

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Ah ich sehe gerade:
Note: The shlex module currently does not support Unicode input.
[mod]shlex[/mod]

Ja, dann... :?

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Karl
User
Beiträge: 252
Registriert: Freitag 29. Juni 2007, 17:49

Irgendwo muss doch die Herausforderung sein, also los, mach dich ran ;)
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

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 ?
Benutzeravatar
Masaru
User
Beiträge: 425
Registriert: Mittwoch 4. August 2004, 22:17

Kurt Z hat geschrieben:...Kommen in strings quotes vor ?
sowohl ' als auch " ?
Wie soll dann escaped werden ?
So :)

Code: Alles auswählen

>>> print '\''
'
>>> print """
"
audax
User
Beiträge: 830
Registriert: Mittwoch 19. Dezember 2007, 10:38

Das sind 2 Zeilen in PyParsing :o
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

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?
Benutzeravatar
Trundle
User
Beiträge: 591
Registriert: Dienstag 3. Juli 2007, 16:45

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.
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

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
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

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

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

Hi wie gesagt kannst du mit RegEx auch escaping rausfiltern, der trick ist das bis zu einem Quote gegriffen werden muss, dem eine gerade Anzahl von Backslashes vorausgehen.

Grundsätzlich stellt sich die Frage wozu du hier eigentlich diese neue Grammatik brauchst .und nicht eine wohl erpobte heranziehst, wie Pythonsyntax, YAML oder JSON.

Beispielcode kann ich dir mangels Pythonkenntnisse nur in Perl geben, Übersezung sollte eine Fleißaufgabe sein:

(meine emacs Indetation geht wg Tabs kaputt)

Code: Alles auswählen

#!/usr/bin/perl

$parse  = << '__HERE';
a=1		b='X  Y\\'		c=True	d="test"		e=None
f='\''	g='"'	h="'"	i='\\\\'		j="True"
__HERE

print qq{
Folgende Ausdrcke werden zerlegt:
$parse

};




# matche alle Zeichenfolgen die mit einer geraden Anzahl \ enden
$escaped_string = qr{
		.*?				# nongreedy
		(?<!\\)		    # kein vorausgehendes '\'
		(?:\\\\)*       # beliebig viele '\\'
}x;



print qq{
String "zerbrseln" und quotes entfernen, ergibt:

};


%dict=(									# Match-Liste paarweise Hash zuweisen
	grep { defined }						# nonmatches ausfiltern
		$parse =~ m/
					   (\w+)					# identifier
					   =						# operator
					   (?:     		            # oder non-grouping
						   '( $escaped_string )' | 	#  singlequote
						   "( $escaped_string )" |	#  doublequote
						   (\w+)			        #  identifier
					   )
					   (?:\s|$)
				   /xg
);



print "$_ => $dict{$_}  \n"	
	for (sort keys %dict) ;


print qq{

 Bei folgender Variante werden die Quotezeichen mitgegriffen
innere matches im Oder entfallen, deswegen mssen auch keine
undef matches ausgefiltert werden.
Vorteil: zwischen a=True und a='True' kann unterschieden werden

};

%dict=(									# Match-Liste paarweise Hash zuweisen
	$parse =~ m/
				   (\w+)					# identifier
				   =						# operator
				   (     		            # oder grouping
					   ' $escaped_string ' | 	#  singlequote
					   " $escaped_string " |	#  doublequote
					   \w+						#  identifier
				   )
				   (?:\s|$)
			   /xg
);

print "$_ => $dict{$_}  \n"	
	for (sort keys %dict) ;

Folgende Ausdrcke werden zerlegt:
a=1 b='X Y\\' c=True d="test" e=None
f='\'' g='"' h="'" i='\\\\' j="True"



String "zerbrseln" und quotes entfernen, ergibt:

a => 1
b => X Y\\
c => True
d => test
e => None
f => \'
g => "
h => '
i => \\\\
j => True


Bei folgender Variante werden die Quotezeichen mitgegriffen
innere matches im Oder entfallen, deswegen mssen auch keine
undef matches ausgefiltert werden.
Vorteil: zwischen a=True und a='True' kann unterschieden werden

a => 1
b => 'X Y\\'
c => True
d => "test"
e => None
f => '\''
g => '"'
h => "'"
i => '\\\\'
j => "True"
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Kurt Z hat geschrieben:Grundsätzlich stellt sich die Frage wozu du hier eigentlich diese neue Grammatik brauchst .und nicht eine wohl erpobte heranziehst, wie Pythonsyntax, YAML oder JSON.
Ich brauche das in PyLucid um in einem Template Tag Parameter setzten zu können. Diese werden dann der view Funktion als Keyword-Arguments übergeben, bsp:

Code: Alles auswählen

{% lucidTag RSS url="http://domain.tld/feed.xml" title="Ein feed" %}
-> RSS.lucidTag(url, title)

Ich forme also aus dem String '''url="http://domain.tld/feed.xml" title="Ein feed"''' ein dict:

Code: Alles auswählen

{ "url": "http://domain.tld/feed.xml", "title": "Ein feed" }

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Kurt Z
User
Beiträge: 23
Registriert: Samstag 17. Mai 2008, 17:43

jens hat geschrieben: bsp:

Code: Alles auswählen

{% lucidTag RSS url="http://domain.tld/feed.xml" title="Ein feed" %}
-> RSS.lucidTag(url, title)
IMHO versuchst du Attributezuwesiungen aus der XML-Grammatik nachzubauen, dann modifiziere doch lieber gleich einen existierenden XML-Parser entsprechend.

Alternative wäre echten Python-Code einzubetten ...

Wozu das Rad neu erfinden?

NACHTRAG: Oder die Grammatik für CSS-Angaben wie im HTML style-tag nutzen.
Antworten