Hybridcode in Shell-Skripten. Variablen teilen

Hybridcode in Shell-Skripten. Variablen teilen

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.

  1. Wie kann ich die Ausgabe des Python-Index im Bash-Skript sammeln? (z. B. in einer Variablen wie $output).

  2. Wie kann ich eine Bash-Variable (z. B. $some_text) an das Python-Skript übergeben?

Antwort1

Eine Variable in Python übertragen

Da (wenn der EOFMarker nicht in Anführungszeichen steht) die Variablenersetzung erfolgt, bevor Text vom Heredoc an pythondie Standardeingabe übergeben wird, können Sie die Variable direkt im Skript einfügen.

python - <<EOF
some_text = "$some_text"
EOF

Wenn some_textwar test, würde Python sehen some_text = "test". Beachten Sie jedoch, dass dies als Code-Injection-Schwachstelle angesehen werden kann. Wenn beispielsweise some_textwar , 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.

verwandte Informationen