2016-05-15 10 views
4
system : Centos 6.7 Lasted 
Shell : bash 
python : 2.6.6 

Es macht mich sehr verwirrt! Beispiel unten:Mischen Python und Bash Shells Xargs Befehl Zweifel

5 Dateien:

a1111 a2222 b1111 b2222 t.py 

t.py Inhalt:

import sys 

if __name__ == '__main__': 
    a1 = sys.argv[1] 
    print 'id(a1)=%s, len(a1)=%s, str(a1)=%s, type(a1)=%s' % (id(a1), len(a1), str(a1), type(a1)) 

tun dies wie:

ls | xargs -I{} echo $(python t.py '{}') 

Ausgang:

id(a1)=139821454683184, len(a1)=2, str(a1)=a1111, type(a1)=<type 'str'> 
id(a1)=139821454683184, len(a1)=2, str(a1)=a2222, type(a1)=<type 'str'> 
id(a1)=139821454683184, len(a1)=2, str(a1)=b1111, type(a1)=<type 'str'> 
id(a1)=139821454683184, len(a1)=2, str(a1)=b2222, type(a1)=<type 'str'> 
id(a1)=139821454683184, len(a1)=2, str(a1)=t.py, type(a1)=<type 'str'> 

meine Frage ist, warum len (a1) = 2, aber str (a1) = A1111?, Ist Stringlänge offensichtlich nicht gleich 2,

mit keinem Echo in Ordnung ist, aber es ist nicht meine Frage. Ich habe Option Verwendung xargs -p die cmd

ls | xargs -I{} python t.py '{}' 
+0

Reproduziert unter OS X auf Python 2.7.10 und 3.5.1 – cdarke

Antwort

6

Der Grund dafür ist, dass der $(python t.py '{}') Ausdruck ausgewertet wird vor es xargs geben wird. $(python t.py '{}') druckt "id (a1) = 139821454683184, len (a1) = 2, str (a1) = {}, type (a1) =", also , das an xargs übergeben wird, das die {} mit jedem der Dateinamen ersetzt ...

Hier ist ein Shell-Spur, die zeigt, was geschieht:

$ set -x # turn on tracing 
$ ls | xargs -I{} echo $(python t.py '{}') 
+ ls 
++ python t.py '{}' 
+ xargs '-I{}' echo 'id(a1)=4560222208,' 'len(a1)=2,' 'str(a1)={},' 'type(a1)=<type' ''\''str'\''>' 
id(a1)=4560222208, len(a1)=2, str(a1)=a1111, type(a1)=<type 'str'> 
id(a1)=4560222208, len(a1)=2, str(a1)=a2222, type(a1)=<type 'str'> 
id(a1)=4560222208, len(a1)=2, str(a1)=b1111, type(a1)=<type 'str'> 
id(a1)=4560222208, len(a1)=2, str(a1)=b2222, type(a1)=<type 'str'> 
id(a1)=4560222208, len(a1)=2, str(a1)=t.py, type(a1)=<type 'str'> 

Die „+“ Linien zeigen, was die Schale tatsächlich ausgeführt wird. (Sie können ignorieren, dass die Argumente zu xargs in einfachen Anführungszeichen stehen, nur weil die Ausgabe von t.py in Wörter aufgeteilt wurde, aber die anderen Shell-Metazeichen in ihrer Ausgabe ignoriert wurden und denselben Effekt direkt in der Befehlszeile erhalten Sie müssten (/ Escape) die Argumente zitieren)

BTW, gibt es eine andere Werbegeschenk, dass das ist, was passiert. die ID die gleiche in jeder Zeile, aber wenn t.py tatsächlich für jede Zeile ausgeführt getrennt wurde, Du erhältst unterschiedliche IDs.

+0

Schöne Erklärung, ein weiteres schnelles Beispiel, das die Länge als zehn Zeichen zeigt (während man vielleicht nicht abgeschlossene Anführungszeichen durch Verwendung von find vermeidet) 'r = $ "Länge = zehn"; finden . -maxdepth 1 -print0 | xargs -I $ r -0 echo $ (python t.py $ r) ' –

2

zu drucken Wenn Sie diese Ausgabe sehen:

len(a1)=2 

Dies ist eigentlich Länge von replStr, die nach -I Option von xargs verwendet wird. Dies ist {} daher Länge ist 2.

Wenn Sie eine andere replStr verwenden.

ls | xargs -I% echo $(python ./t.py '%') 

dann werden Sie len=1 in der Ausgabe sehen, da Länge von %1 ist.

id(a1)=4342949968, len(a1)=1, str(a1)=a1111, type(a1)=<type 'str'> 
id(a1)=4342949968, len(a1)=1, str(a1)=a2222, type(a1)=<type 'str'> 
id(a1)=4342949968, len(a1)=1, str(a1)=b1111, type(a1)=<type 'str'> 
id(a1)=4342949968, len(a1)=1, str(a1)=b2222, type(a1)=<type 'str'> 
id(a1)=4342949968, len(a1)=1, str(a1)=t.py, type(a1)=<type 'str'> 

Grund dafür ist, wenn Sie verwenden:

ls | xargs -I{} echo $(python ./t.py '{}') 

Sie anrufen eigentlich Python-Programm in einer Subshell und das ist vorbei wörtliche {} zu Python.

Hier ist die Debug-Ausgabe, das gleiche zeigen:

bash -cx 'ls | xargs -I{} echo $(python ./t.py "{}")' >/dev/null 
+ ls 
++ python ./t.py '{}' 
+ xargs '-I{}' echo 'id(a1)=4460329040,' 'len(a1)=2,' 'str(a1)={},' 'type(a1)=<type' ''\''str'\''>' 

jedoch von Ihnen:

bash -cx 'ls | xargs -I{} python ./t.py "{}"' >/dev/null 
+ ls 
+ xargs '-I{}' python ./t.py '{}' 

Sie unterschiedliches Verhalten in der Art und Weise xargs sehen kann, ist Python Kommandozeile aufrufen.

+0

Es ist die Länge der Parameter-Zeichenfolge, Sie müssen nicht ändern "-I", um zu sehen: 'ls | xargs -I {} echo $ (python3 gash.py '{}') 'gibt eine Länge von 4 an. Die Frage ist" warum? " Die Zeichenfolge, die python in 'sys.argv [1]' bekommt, ist nicht '{}'. Entschuldigung, aber alles, was Sie getan haben, ist das Problem zu beschreiben, nicht zu erklären. – cdarke

+0

Ich habe auch eine Debug-Ausgabe hinzugefügt, um zu zeigen, warum 'str (a1) = {}' nicht an Python übergeben wird. – anubhava

+0

Wenn Python eine Zeichenfolge mit 5 Zeichen gesendet wird, dann wird die Länge als 2 gemeldet Ich denke, Sie haben das erklärt. Übrigens, ich kann es auch nicht erklären. – cdarke