Mehrzeilige Anweisungen in der einzeiligen Befehlszeile ausführen?

197

Ich verwende Python mit -c, um eine Einzeiler-Schleife auszuführen, dh:

$ python -c "for r in range(10): print 'rob'"

Das funktioniert gut. Wenn ich jedoch ein Modul vor der for-Schleife importiere, wird ein Syntaxfehler angezeigt:

$ python -c "import sys; for r in range(10): print 'rob'"
  File "<string>", line 1
    import sys; for r in range(10): print 'rob'
              ^
SyntaxError: invalid syntax

Irgendeine Idee, wie dies behoben werden kann?

Es ist mir wichtig, dies als Einzeiler zu haben, damit ich es in ein Makefile aufnehmen kann.

Martineau
quelle

Antworten:

181

du könntest es tun

echo -e "import sys\nfor r in range(10): print 'rob'" | python

oder ohne Rohre:

python -c "exec(\"import sys\nfor r in range(10): print 'rob'\")"

oder

(echo "import sys" ; echo "for r in range(10): print 'rob'") | python

oder @ SilentGhosts Antwort / @ Crasts Antwort

jspcal
quelle
Die letzte Option funktioniert hervorragend mit Python3 in Windows
Ian Ellis
1
@RudolfOlah Ich hoffe, Sie wissen es jetzt, aber nur als Referenz müssen Sie die print-Anweisung für Python3 + -Versionen wie:python -c "exec(\"import sys\nfor r in range(10): print('rob')\")"
systrigger
@systrigger danke, ich habe verpasst, dass ich glaube, ich war in Eile und habe nicht
89

Dieser Stil kann auch in Makefiles verwendet werden (und tatsächlich wird er ziemlich oft verwendet).

python - <<EOF
import sys
for r in range(3): print 'rob'
EOF

oder

python - <<-EOF
    import sys
    for r in range(3): print 'rob'
EOF

Im letzteren Fall werden auch führende Tabulatorzeichen entfernt (und es kann ein strukturierter Ausblick erzielt werden).

Anstelle von EOF kann jedes Markierungswort stehen, das nicht im Dokument hier am Anfang einer Zeile erscheint (siehe auch hier Dokumente in der Bash-Manpage oder hier ).

xorho
quelle
9
Nett. Um auch Argumente zu übergeben , platzieren Sie sie einfach nach <<EOF. Beachten Sie jedoch, dass es besser ist, das Trennzeichen zu zitieren - z. B. <<'EOF'-, um den Inhalt des Here-Dokuments vor Erweiterungen der Shell im Voraus zu schützen .
mklement0
56

Das Problem liegt nicht in der import-Anweisung, sondern darin, dass sich etwas vor der for-Schleife befindet. Oder genauer gesagt, alles, was vor einem Inline-Block erscheint.

Zum Beispiel funktionieren diese alle:

python -c "import sys; print 'rob'"
python -c "import sys; sys.stdout.write('rob\n')"

Wenn der Import als Anweisung ein Problem wäre, würde dies funktionieren, aber es funktioniert nicht:

python -c "__import__('sys'); for r in range(10): print 'rob'"

Für Ihr sehr einfaches Beispiel könnten Sie es wie folgt umschreiben:

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

Lambdas können jedoch nur Ausdrücke ausführen, keine Anweisungen oder mehrere Anweisungen, sodass Sie möglicherweise immer noch nicht in der Lage sind, das zu tun, was Sie tun möchten. Zwischen Generatorausdrücken, Listenverständnis, Lambdas, sys.stdout.write, der eingebauten "Map" und einer kreativen Zeichenfolgeninterpolation können Sie jedoch einige leistungsstarke Einzeiler erstellen.

Die Frage ist, wie weit möchten Sie gehen und an welchem ​​Punkt ist es nicht besser, eine kleine .pyDatei zu schreiben, die Ihr Makefile stattdessen ausführt?

Crast
quelle
31


- Damit diese Antwort auch mit Python 3.x funktioniert , printwird als Funktion aufgerufen : In 3.x funktioniert nur print('foo') , während 2.x auch akzeptiert print 'foo'.
- Eine plattformübergreifende Perspektive mit Windows finden Sie in der hilfreichen Antwort von kxr .

In bash, kshoderzsh :

Verwenden Sie eine ANSI-Zeichenfolge mit C-Anführungszeichen ( $'...'), mit \nder Zeilenumbrüche dargestellt werden können, die zu tatsächlichen Zeilenumbrüchen erweitert werden, bevor die Zeichenfolge an Folgendes übergeben wird python:

python -c $'import sys\nfor r in range(10): print("rob")'

Beachten Sie die Anweisungen \nzwischen importund for, um einen Zeilenumbruch zu bewirken.

Um Shell-Variablenwerte an einen solchen Befehl zu übergeben, ist es am sichersten, Argumente zu verwenden und über sys.argvdas Python-Skript darauf zuzugreifen :

name='rob' # value to pass to the Python script
python -c $'import sys\nfor r in range(10): print(sys.argv[1])' "$name"

Im Folgenden finden Sie eine Erläuterung der Vor- und Nachteile der Verwendung einer (mit Escape-Sequenz vorverarbeiteten) Befehlszeichenfolge in doppelten Anführungszeichen mit eingebetteten Shell-Variablenreferenzen.

So arbeiten Sie sicher mit $'...'Saiten:

  • Doppelte \ Instanzen in Ihrem ursprünglichen Quellcode.
    • \<char>Sequenzen - wie \nin diesem Fall, aber auch die üblichen Verdächtigen wie \t, \r, \b- werden durch erweitert $'...'(siehe man printffür die unterstützten Fluchten)
  • Escape- 'Instanzen als \'.

Wenn Sie POSIX-konform bleiben müssen :

Verwendung printfmit einer Befehlssubstitution :

python -c "$(printf %b 'import sys\nfor r in range(10): print("rob")')"

So arbeiten Sie sicher mit dieser Art von Zeichenfolge:

  • Doppelte \ Instanzen in Ihrem ursprünglichen Quellcode.
    • \<char>Sequenzen - wie \nin diesem Fall, aber auch die üblichen Verdächtigen wie \t, \r, \b- durch erweitert werden printf(siehe man printffür die unterstützten Escape - Sequenzen).
  • Übergeben Sie einen einfachen Anführungszeichen Zeichenfolge printf %bund entkommen eingebettete einfache Anführungszeichen als '\'' (sic).

    • Die Verwendung von einfachen Anführungszeichen schützt den Inhalt der Zeichenfolge vor der Interpretation durch die Shell .

      • Für kurze Python-Skripte (wie in diesem Fall) können Sie jedoch eine Zeichenfolge in doppelten Anführungszeichen verwenden, um Shell- Variablenwerte in Ihre Skripte aufzunehmen - sofern Sie die damit verbundenen Fallstricke kennen (siehe nächster Punkt). Beispielsweise wird die Shell $HOMEauf das Home-Verzeichnis des aktuellen Benutzers erweitert . im folgenden Befehl:

        • python -c "$(printf %b "import sys\nfor r in range(10): print('rob is $HOME')")"
      • Der allgemein bevorzugte Ansatz besteht jedoch darin, Werte aus der Shell über Argumente zu übergeben und über sys.argvin Python darauf zuzugreifen . Das Äquivalent des obigen Befehls ist:

        • python -c "$(printf %b 'import sys\nfor r in range(10): print("rob is " + sys.argv[1])')" "$HOME"
    • Die Verwendung einer Zeichenfolge in doppelten Anführungszeichen ist zwar bequemer - Sie können eingebettete einfache Anführungszeichen ohne Leerzeichen und eingebettete doppelte Anführungszeichen verwenden, da \"- die Zeichenfolge auch von der Shell interpretiert werden kann, was möglicherweise beabsichtigt ist oder nicht. $und `Zeichen im Quellcode, die nicht für die Schale gemeint können einen Syntaxfehler verursachen oder die Zeichenfolge unerwartet ändern.

      • Darüber hinaus kann die eigene \Verarbeitung der Shell in Zeichenfolgen in doppelten Anführungszeichen stören. Damit Python beispielsweise eine Literalausgabe erzeugt ro\b, müssen Sie ro\\bdiese übergeben. Mit einer '...'Shell-Zeichenfolge und doppelten \ Instanzen erhalten wir:
        python -c "$(printf %b 'import sys\nprint("ro\\\\bs")')" # ok: 'ro\bs'
        Im Gegensatz dazu funktioniert dies nicht wie beabsichtigt mit einer "..."Shell-Zeichenfolge:
        python -c "$(printf %b "import sys\nprint('ro\\\\bs')")" # !! INCORRECT: 'rs'
        Die Shell interpretiert beide "\b" und "\\b"als Literal \bund erfordert eine schwindelerregende Anzahl zusätzlicher \Instanzen, um den gewünschten Effekt zu erzielen:
        python -c "$(printf %b "import sys\nprint('ro\\\\\\\\bs')")"

Um den Code via zu passierenstdin anstatt -c:

Hinweis: Ich bin mit Schwerpunkt auf einzelne hier -Linie Lösungen; xorho Antwort zeigt , wie eine mehrzeilige verwenden , hier-Dokument - sicher sein , zu zitieren , das Trennzeichen, jedoch; Beispiel: Es <<'EOF'sei denn, Sie möchten ausdrücklich, dass die Shell die Zeichenfolge vorne erweitert (was mit den oben genannten Einschränkungen verbunden ist).


In bash, kshoderzsh :

Kombinieren Sie eine ANSI C-Zeichenfolge ( $'...') mit einer Here-Zeichenfolge ( <<<...):

python - <<<$'import sys\nfor r in range(10): print("rob")'

-weist pythonexplizit an, von stdin zu lesen (was standardmäßig der Fall ist). -ist in diesem Fall optional, aber wenn Sie auch Argumente an die Skripte übergeben möchten, benötigen Sie diese, um das Argument von einem Skriptdateinamen zu unterscheiden:

python - 'rob' <<<$'import sys\nfor r in range(10): print(sys.argv[1])'

Wenn Sie POSIX-konform bleiben müssen :

Verwenden Sie es printfwie oben, jedoch mit einer Pipeline , um die Ausgabe über stdin zu übergeben:

printf %b 'import sys\nfor r in range(10): print("rob")' | python

Mit einem Argument:

printf %b 'import sys\nfor r in range(10): print(sys.argv[1])' | python - 'rob'
mklement0
quelle
2
Dies sollte die gewählte Antwort sein!
Debüt
1
Dies funktioniert auch und ist wahrscheinlich die beste Antwort, da es eine vollständige Erklärung enthält, Bravo!
22

Irgendeine Idee, wie dies behoben werden kann?

Ihr Problem entsteht durch die Tatsache, dass Python-Anweisungen, die durch getrennt ;sind, nur "kleine Anweisungen" sein dürfen, die alle Einzeiler sind. Aus der Grammatikdatei in den Python-Dokumenten :

stmt: simple_stmt | compound_stmt
simple_stmt: small_stmt (';' small_stmt)* [';'] NEWLINE
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
             import_stmt | global_stmt | nonlocal_stmt | assert_stmt)

Zusammengesetzte Anweisungen können nicht über Semikolons in dieselbe Zeile mit anderen Anweisungen eingefügt werden. Daher ist es -csehr unpraktisch , dies mit dem Flag zu tun .

Wenn ich Python in einer Bash-Shell-Umgebung demonstriere, finde ich es sehr nützlich, zusammengesetzte Anweisungen einzuschließen. Die einzige einfache Möglichkeit, dies zuverlässig zu tun, sind Heredocs (eine Posix-Shell-Sache).

Heredocs

Verwenden Sie einen heredoc (erstellt mit <<) und der Python Kommandozeilen - Schnittstelle Option , -:

$ python - <<-"EOF"
        import sys                    # 1 tab indent
        for r in range(10):           # 1 tab indent
            print('rob')              # 1 tab indent and 4 spaces
EOF

Durch Hinzufügen von -after <<(the <<-) können Sie Tabulatoren zum Einrücken verwenden (Stackoverflow konvertiert Tabulatoren in Leerzeichen, daher habe ich 8 Leerzeichen eingerückt, um dies hervorzuheben). Die führenden Registerkarten werden entfernt.

Sie können es ohne die Registerkarten mit nur tun <<:

$ python - << "EOF"
import sys
for r in range(10):
    print('rob')
EOF

Das Setzen von Anführungszeichen EOFverhindert die Erweiterung von Parametern und Arithmetik . Dies macht den Heredoc robuster.

Bash mehrzeilige Saiten

Wenn Sie doppelte Anführungszeichen verwenden, erhalten Sie eine Shell-Erweiterung:

$ python -c "
> import sys
> for p in '$PATH'.split(':'):
>     print(p)
> "
/usr/sbin
/usr/bin
/sbin
/bin
...

Verwenden Sie einfache Anführungszeichen, um eine Shell-Erweiterung zu vermeiden:

$ python -c '
> import sys
> for p in "$PATH".split(":"):
>     print(p)
> '
$PATH

Beachten Sie, dass wir die Anführungszeichen in den Literalen in Python austauschen müssen - wir können grundsätzlich keine Anführungszeichen verwenden, die von BASH interpretiert werden. Wir können sie zwar abwechseln, wie wir es in Python können - aber das sieht schon ziemlich verwirrend aus, weshalb ich dies nicht empfehle:

$ python -c '
import sys
for p in "'"$PATH"'".split(":"):
    print(p)
'
/usr/sbin
/usr/bin
/sbin
/bin
...

Kritik der akzeptierten Antwort (und anderer)

Dies ist nicht sehr gut lesbar:

echo -e "import sys\nfor r in range(10): print 'rob'" | python

Nicht sehr gut lesbar und im Fehlerfall zusätzlich schwer zu debuggen:

python -c "exec(\"import sys\\nfor r in range(10): print 'rob'\")"

Vielleicht etwas lesbarer, aber immer noch ziemlich hässlich:

(echo "import sys" ; echo "for r in range(10): print 'rob'") | python

Sie werden eine schlechte Zeit haben, wenn Sie "in Ihrer Python haben:

$ python -c "import sys
> for r in range(10): print 'rob'"

Missbrauche mapoder liste kein Verständnis auf, um for-Schleifen zu erhalten:

python -c "import sys; map(lambda x: sys.stdout.write('rob%d\n' % x), range(10))"

Diese sind alle traurig und schlecht. Tu sie nicht.

Aaron Hall
quelle
3
++ für die Grammatikinfo; Das (nicht expandierende) Here-Doc ist praktisch und die robusteste Lösung, aber offensichtlich kein Einzeiler. Wenn eine einzeilige Lösung ist ein Muss, einen ANSI - C-String in Anführungszeichen verwenden ( bash, kshoder zsh) ist eine vernünftige Lösung: python -c $'import sys\nfor r in range(10): print(\'rob\')'(nur zur Sorge Apostrophe haben würde über Flucht (die man durch doppelte Anführungszeichen vermeiden kann) und Backslashes).
mklement0
14

Verwenden Sie einfach return und geben Sie es in die nächste Zeile ein:

user@host:~$ python -c "import sys
> for r in range(10): print 'rob'"
rob
rob
...
SilentGhost
quelle
6
Im Ernst, Sie werden sich etwas verstauchen, wenn Sie dies weiter tun. python $(srcdir)/myscript.pyfür große Gerechtigkeit.
Jason Orendorff
10

$ python2.6 -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

Funktioniert gut. Verwenden Sie "[]", um Ihre for-Schleife zu inline.

Pierre Pericard
quelle
9

Das Problem liegt nicht bei der importAussage. Das Problem ist, dass die Kontrollflussanweisungen in einem Python-Befehl nicht inline funktionieren. Ersetzen Sie diese importAnweisung durch eine andere Anweisung, und Sie werden das gleiche Problem sehen.

Denken Sie darüber nach: Python kann unmöglich alles inline. Es verwendet Einrückungen, um den Kontrollfluss zu gruppieren.

David Berger
quelle
7

Wenn Ihr System Posix.2-kompatibel ist, sollte es das folgende printfDienstprogramm bereitstellen :

$ printf "print 'zap'\nfor r in range(3): print 'rob'" | python
zap
rob
rob
rob
Alex Martelli
quelle
2
Gute Lösung, aber ich schlage vor, sie printf %b '...' | pythonfür zusätzliche Robustheit zu verwenden, da sie verhindert, dass printfSequenzen wie %d(Formatbezeichner) in der Eingabezeichenfolge interpretiert werden . Sofern Sie nicht explizit Shell-Erweiterungen auf Ihre Python-Befehlszeichenfolge im Voraus anwenden möchten (was verwirrend sein kann), ist es besser, 'einfache Anführungszeichen für das äußere Anführungszeichen zu verwenden , um sowohl die Erweiterungen als auch die von der Shell angewendete Spielverarbeitung zu vermeiden zu Anführungszeichen in doppelten Anführungszeichen.
mklement0
5

single/double quotesund backslashüberall:

$ python -c 'exec("import sys\nfor i in range(10): print \"bob\"")'

Viel besser:

$ python -c '
> import sys
> for i in range(10):
>   print "bob"
> '
kev
quelle
so. viel. besser.
Marc
4

(antwortete am 23. November 10 um 19:48 Uhr ) Ich bin nicht wirklich ein großer Pythoner - aber ich habe diese Syntax einmal gefunden und vergessen, woher sie stammt, also dachte ich, ich würde sie dokumentieren:

Wenn Sie sys.stdout.writeanstelle von print( der Unterschied besteht darin, dass sys.stdout.writeArgumente als Funktion in Klammern verwendet werden - wohingegen printdies nicht der Fall ist ), können Sie bei einem Einzeiler die Reihenfolge des Befehls umkehren und fordas Semikolon entfernen. und Einschließen des Befehls in eckige Klammern, dh:

python -c "import sys; [sys.stdout.write('rob\n') for r in range(10)]"

Habe keine Ahnung wie diese Syntax in Python heißen würde :)

Hoffe das hilft,

Prost!


(EDIT Di Apr 9 20:57:30 2013) Nun, ich glaube, ich habe endlich herausgefunden, worum es bei diesen eckigen Klammern in Einzeilern geht. sie sind "Listenverständnisse" (anscheinend); Beachten Sie dies zuerst in Python 2.7:

$ STR=abc
$ echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); print a"
<generator object <genexpr> at 0xb771461c>

Der Befehl in runden Klammern / Klammern wird also als "Generatorobjekt" angesehen. Wenn wir es durch Aufrufen "durchlaufen", wird next()der Befehl in der Klammer ausgeführt (beachten Sie das "abc" in der Ausgabe):

$ echo $STR | python -c "import sys,re; a=(sys.stdout.write(line) for line in sys.stdin); a.next() ; print a"
abc
<generator object <genexpr> at 0xb777b734>

Wenn wir jetzt eckige Klammern verwenden, müssen Sie nicht aufrufen next(), damit der Befehl ausgeführt wird. Er wird sofort nach der Zuweisung ausgeführt. jedoch zeigt spätere Untersuchung , dass aist None:

$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; print a"
abc
[None]

Dies lässt nicht viele Informationen zu suchen, für den Fall der eckigen Klammern - aber ich bin auf diese Seite gestoßen, die meiner Meinung nach erklärt:

Python Tipps und Tricks - Erste Ausgabe - Python Tutorials | Dream.In.Code :

Wenn Sie sich erinnern, ist das Standardformat eines Generators für eine einzelne Zeile eine Art 'for'-Schleife in Klammern. Dadurch wird ein iterierbares "One-Shot" -Objekt erstellt, über das Sie nur in eine Richtung iterieren können und das Sie am Ende nicht mehr verwenden können.

Ein 'Listenverständnis' sieht fast genauso aus wie ein normaler einzeiliger Generator, außer dass die regulären Klammern - () - durch eckige Klammern - [] ersetzt werden. Der Hauptvorteil des alistischen Verständnisses besteht darin, dass eine "Liste" anstelle eines "einmaligen" iterierbaren Objekts erstellt wird, sodass Sie es durchgehen, Elemente hinzufügen, sortieren usw. können.

Und in der Tat ist es eine Liste - es ist nur das erste Element, das zu keinem wird, sobald es ausgeführt wird:

$ echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin].__class__"
abc
<type 'list'>
$ echo $STR | python -c "import sys,re; print [sys.stdout.write(line) for line in sys.stdin][0]"
abc
None

Listenverständnisse sind ansonsten in 5. Datenstrukturen: 5.1.4 dokumentiert . Listenverständnisse - Python v2.7.4-Dokumentation als "Listenverständnisse bieten eine übersichtliche Möglichkeit zum Erstellen von Listen"; vermutlich kommt hier die eingeschränkte "Ausführbarkeit" von Listen in Einzeilern ins Spiel.

Nun, ich hoffe, ich bin hier nicht zu daneben ...

EDIT2: und hier ist eine einzeilige Befehlszeile mit zwei nicht verschachtelten for-Schleifen; beide in eckigen Klammern "Listenverständnis" eingeschlossen:

$ echo $STR | python -c "import sys,re; a=[sys.stdout.write(line) for line in sys.stdin]; b=[sys.stdout.write(str(x)) for x in range(2)] ; print a ; print b"
abc
01[None]
[None, None]

Beachten Sie, dass die zweite "Liste" bjetzt zwei Elemente enthält, da ihre for-Schleife explizit zweimal ausgeführt wurde. Das Ergebnis von war jedoch sys.stdout.write()in beiden Fällen (anscheinend) None.

sdaau
quelle
4

Diese Variante ist am portabelsten, um mehrzeilige Skripte unter Windows und * nix, py2 / 3, ohne Pipes in die Befehlszeile zu stellen:

python -c "exec(\"import sys \nfor r in range(10): print('rob') \")"

(Keines der anderen hier gezeigten Beispiele hat dies bisher getan)

Ordentlich unter Windows ist:

python -c exec"""import sys \nfor r in range(10): print 'rob' """
python -c exec("""import sys \nfor r in range(10): print('rob') """)

Ordentlich auf bash / * nix ist:

python -c $'import sys \nfor r in range(10): print("rob")'

Diese Funktion verwandelt jedes mehrzeilige Skript in einen tragbaren Befehls-Einzeiler:

def py2cmdline(script):
    exs = 'exec(%r)' % re.sub('\r\n|\r', '\n', script.rstrip())
    print('python -c "%s"' % exs.replace('"', r'\"'))

Verwendung:

>>> py2cmdline(getcliptext())
python -c "exec('print \'AA\tA\'\ntry:\n for i in 1, 2, 3:\n  print i / 0\nexcept:\n print \"\"\"longer\nmessage\"\"\"')"

Eingabe war:

print 'AA   A'
try:
 for i in 1, 2, 3:
  print i / 0
except:
 print """longer
message"""
kxr
quelle
++ für den plattformübergreifenden Winkel und den Konverter. Ihr erster Befehl ist in Bezug auf die Portabilität so gut wie nie zuvor (abgesehen von PowerShell), aber letztendlich gibt es keine einzige, vollständig robuste plattformübergreifende Syntax, da die Notwendigkeit, doppelte Anführungszeichen zu verwenden, das Risiko unerwünschter Shell-Erweiterungen mit sich bringt Windows, bei dem andere Zeichen als POSIX-ähnliche Shells entfernt werden müssen. In PowerShell v3 oder höher können Sie Ihre Befehlszeilen zum Laufen bringen, indem Sie die Option "Stop-Parsing" --%vor dem Befehlszeichenfolgenargument einfügen .
mklement0
@ mklement0 " unerwünschte Shell-Erweiterungen ": Nun , das Einfügen von Shell-Erweiterungen in so etwas wie print "path is %%PATH%%"resp. print "path is $PATH"ist normalerweise die Option, die man in einem Skript oder einer Befehlszeile haben möchte - es sei denn, man entgeht den für die Plattform üblichen Dingen. Gleiches gilt für andere Sprachen. (Die Python-Syntax selbst schlägt nicht regelmäßig die Verwendung von% und $ in konkurrierender Weise vor.)
kxr
Wenn Sie Shell-Variablenreferenzen direkt in den Python-Quellcode einfügen, ist dieser per Definition nicht portierbar. Mein Punkt ist, dass selbst wenn Sie stattdessen plattformspezifische Referenzen in separaten Variablen erstellt haben, die Sie als Argumente an einen einzelnen "Shell-freien" Python-Befehl übergeben, dies möglicherweise nicht immer funktioniert, da Sie die Zeichenfolge in doppelten Anführungszeichen nicht portabel schützen können : Was ist beispielsweise, wenn Sie ein Literal $foo in Ihrem Python-Code benötigen ? Wenn Sie es \$foozugunsten von POSIX-ähnlichen Shells entkommen, sehen Sie cmd.exeimmer noch das Extra \ . Es mag selten sein, aber es lohnt sich zu wissen.
mklement0
Der Versuch, dies in Windows PowerShell zu tun, besteht jedoch darin, dass Python -c exec ("" "..." ") überhaupt keine Ausgabe erzeugt, unabhängig davon, ob der Code in ... ausgeführt werden kann oder nicht; Ich könnte dort jeden Kauderwelsch hinlegen, und das Ergebnis wäre das gleiche. Ich habe das Gefühl, dass die Shell sowohl den stdout- als auch den stderr-Stream "frisst" - wie kann ich sie dazu bringen, sie auszuspucken?
Yury
1

Wenn ich das tun musste, benutze ich

python -c "$(echo -e "import sys\nsys.stdout.write('Hello World!\\\n')")"

Beachten Sie den dreifachen Backslash für den Zeilenumbruch in der Anweisung sys.stdout.write.

Devilholk
quelle
Dies funktioniert, aber da Sie verwenden echo -e, was nicht dem Standard entspricht und erfordert bash, kshoder zshSie können auch eine $'...'Zeichenfolge direkt verwenden, was auch das python -c $'import sys\nsys.stdout.write("Hello World!\\n")'
Escapezeichen
Diese Antwort funktioniert, die anderen Antworten funktionieren nicht für Python3
1

Ich wollte eine Lösung mit folgenden Eigenschaften:

  1. Lesbar
  2. Lesen Sie stdin, um die Ausgabe anderer Tools zu verarbeiten

Beide Anforderungen wurden in den anderen Antworten nicht angegeben. So lesen Sie stdin, während Sie alles in der Befehlszeile ausführen:

grep special_string -r | sort | python3 <(cat <<EOF
import sys
for line in sys.stdin:
    tokens = line.split()
    if len(tokens) == 4:
        print("%-45s %7.3f    %s    %s" % (tokens[0], float(tokens[1]), tokens[2], tokens[3]))
EOF
)
Nick
quelle
0

Es gibt noch eine weitere Option: sys.stdout.write gibt None zurück, wodurch die Liste leer bleibt

cat somefile.log | python -c "sys importieren; [Zeile für Zeile in sys.stdin wenn sys.stdout.write (Zeile * 2)]"

user993533
quelle
0

Wenn Sie stdin nicht berühren und simulieren möchten, als hätten Sie "python cmdfile.py" übergeben, können Sie mit einer Bash-Shell Folgendes tun:

$ python  <(printf "word=raw_input('Enter word: ')\nimport sys\nfor i in range(5):\n    print(word)")

Wie Sie sehen können, können Sie stdin zum Lesen von Eingabedaten verwenden. Intern erstellt die Shell die temporäre Datei für den Inhalt des Eingabebefehls.

Thava
quelle
++ für das nicht "Aufbrauchen" von stdin mit dem Skript selbst (obwohl -c "$(...)"es dasselbe tut und POSIX-kompatibel ist); um dem <(...)Konstrukt einen Namen zu geben : Prozesssubstitution ; es funktioniert auch in kshund zsh.
mklement0