Diese Antwortbeschreibt, wie man einen mehrzeiligen Python-Ausschnitt von der Kommandozeile in einem Terminal aus ausführt. Mir ist aufgefallen, dass die Antwort in Shell-Skripten hervorragend funktioniert, sogar mit verschachtelter Einrückung, was sehr schön ist, z. B.
#!/bin/bash
some_text="Hello world"
echo $some_text
cat <<EOF | python -
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
Drucke:
0
hello
hello
1
hello
hello
2
hello
hello
Allerdings habe ich Schwierigkeiten, Variablen zwischen dem Shell-Skript und dem Python-Snippet zu teilen.
Wie kann ich die Ausgabe des Python-Index im Bash-Skript sammeln? (z. B. in einer Variablen wie
$output
).Wie kann ich eine Bash-Variable (z. B.
$some_text
) an das Python-Skript übergeben?
Antwort1
Eine Variable in Python übertragen
Da (wenn der EOF
Marker nicht in Anführungszeichen steht) die Variablenersetzung erfolgt, bevor Text vom Heredoc an python
die Standardeingabe übergeben wird, können Sie die Variable direkt im Skript einfügen.
python - <<EOF
some_text = "$some_text"
EOF
Wenn some_text
war test
, würde Python sehen some_text = "test"
. Beachten Sie jedoch, dass dies als Code-Injection-Schwachstelle angesehen werden kann. Wenn beispielsweise some_text
war , würde Python sehen:"; import os; os.system("evil-command"); x = "
some_text = ""; import os; os.system("evil-command"); x = ""
und führe diesen bösen Befehl aus.
Wenn Sie Ihren Python-Code ohne Änderungen direkt in ein Skript einfügen möchten, können Sie Ihre Variable exportieren.
export some_text
und verwenden Sie os.environ
, um es abzurufen.
some_text = os.environ['some_text']
Das ist ein viel vernünftigerer/sichererer Ansatz.
Abrufen der Ausgabe aus Python
Sie können die Befehlsersetzung verwenden, um die Ausgabe des Skripts zu sammeln.
output=$(
python - <<EOF
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
)
(Beachten Sie, dass alle nachstehenden Zeilenumbruchzeichen entfernt werden)
Antwort2
Das Problem bei Ihrem Ansatz besteht darin, dass das eingebettete Python-Skript keinen Zugriff mehr auf den ursprünglichen Standardeingang hat (da sein Standardeingang … es selbst ist).
Wenn das ein Problem ist, können Sie schreiben:
python -c '
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
'
Oder wenn das Python-Skript einfache Anführungszeichen enthalten darf:
python -c "$(cat << 'EOF'
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
)"
Oder:
python <(cat << 'EOF'
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
)
Antwort3
Verwenden Sie als Dateinamen einen Bindestrich:
ruby - a b <<'END'
puts ARGV.join(",")
END
python - a b <<'END'
import sys
print ",".join(sys.argv[1:])
END
Ich weiß nicht, ob sys.argv[1:]
das in Python die richtige Vorgehensweise ist. Für -e / -c können Sie das Ende der Argumente mit -- angeben:
set -- -a -b -c
ruby -e 'puts ARGV.join(",")' -- "$@"
python -c 'import sys; print ",".join(sys.argv[2:])' -- "$@"
Ausgabe erfassen und STDERR umleiten:
x=$(ruby <<'END' 2> /dev/null
puts "a"
abort "b"
END
)
Antwort4
1) Sie könnten Variablenzuweisungen in eine Datei in Python schreiben und diese dann in Ihrem Bash-Skript als Quelle verwenden.
2) Da Ihr Wort (EOF) nicht in Anführungszeichen steht, werden alle Zeilen des Here-Dokuments einer Parametererweiterung unterzogen. Sie können dies verwenden, um Dinge an das Python-Skript zu übergeben.