2010-02-03 5 views
37

Ich möchte den Text von kurzen Python-Skripten in einem Bash-Skript einbetten, zum Beispiel in meinem .bash_profile. Was ist der beste Weg, um so etwas zu tun?Einbetten kurzer Python-Skripte in ein Bash-Skript

Die Lösung, die ich bisher habe, ist die Python-Interpreter mit der -c Option zu nennen, und sagen Sie dem Dolmetscher zu exec was auch immer es von stdin liest. Von dort aus kann ich einfache Werkzeuge wie die folgenden bauen, so dass ich Text zur Verwendung in meiner interaktiven Eingabeaufforderung verarbeiten:

function pyexec() { 
    echo "$(/usr/bin/python -c 'import sys; exec sys.stdin.read()')" 
} 

function traildirs() { 
    pyexec <<END 
trail=int('${1:-3}') 
import os 
home = os.path.abspath(os.environ['HOME']) 
cwd = os.environ['PWD'] 
if cwd.startswith(home): 
    cwd = cwd.replace(home, '~', 1) 
parts = cwd.split('/') 
joined = os.path.join(*parts[-trail:]) 
if len(parts) <= trail and not joined.startswith('~'): 
    joined = '/'+joined 
print joined 
END 
} 

export PS1="\h [\$(traildirs 2)] % " 

Dieser Ansatz, wenn auch etwas komisch für mich riecht, und ich frage mich, welche Alternativen es zu tun so könnte es sein.

Meine Bash Scripting Fähigkeiten sind ziemlich rudimentär, daher bin ich besonders interessiert zu hören, ob ich aus der Sicht des Bash Interpreters etwas albernes mache.

+0

können Sie deutlicher sagen, was ist es eigentlich versuchen Sie zu tun? von dem, was ich sehe, wird Python nicht wirklich benötigt. Sie können die meisten Dinge mit der Shell machen. – ghostdog74

+1

@ ghostdog74: nichts wirklich tiefer als ich sagte; Ich bin nur ein viel besserer Python-Programmierer als ein Bash-Programmierer, und IMO Python ist im Allgemeinen leistungsfähiger als bash. Es könnte nützlich sein, Funktionen zu implementieren, die in einem Bash-Skript in Python verwendet werden, und manchmal nicht von externen Dateien abhängig sind. Ich mache endlich den Wechsel von Tcsh zu Bash (nach 15 Jahren), und ich versuche, die Shell nach meinem Willen/Vorlieben zu biegen. –

+0

-1: Warum nicht einfach eine .py-Moduldatei erstellen? Warum erzwingen Sie die Python in ein Shell-Skript, wenn eine bessere Lösung (normalerweise) die Verwendung der Shell vollständig beendet? –

Antwort

27

Das Python-Interpreter übernimmt - auf der Kommandozeile als Synonym für stdin so können Sie die Anrufe ersetzen pyexec:

python - <<END 

here Befehlszeilen Referenz.

+1

Huh - Ich hatte eine Textsuche auf der Python Man Seite gemacht, und der Text 'stdin' ist nicht drin. Wenn man genauer hinsieht, ist "Standard Input". Do. –

+0

Einverstanden der Heredoc-Ansatz kann funktionieren.Es gibt jedoch Dinge, auf die man achten sollte: (1) Wenn der Heredoc-Marker ("END" in Neds Beispiel) in der Spalte 0 des Python-Skripts vorkommt, wird das Heredoc früh enden; (2) Variationen des heredoc-Markers (mit oder ohne vorangestelltem '-') beeinflussen, ob Tabulatoren und Leerzeichen erhalten bleiben; und (3) syntaktische Überlappung zwischen Python und Bash, wenn die variable Expansion eingeschaltet ist (der Heredoc-Marker nicht angegeben), z. '$ {1}' könnte rechtmäßig in einem Python-String-Format-Spezifizierer erscheinen, würde aber durch einen Bash-Kommandozeilenparameter ersetzt, wenn der Heredoc-Marker nicht in Anführungszeichen steht. –

+1

Seien Sie vorsichtig, wie Sie den Heredoc-Marker benennen. Wenn es wie in Ihrem Beispiel nicht angegeben ist, wird die Shell-Erweiterung innerhalb der heredoc-Zeichenfolge ausgeführt. Wenn dein Python-Code zum Beispiel nur 'print '$ SHELL'' wäre, wäre die Ausgabe'/bin/bash' oder was auch immer deine Shell ist. Wenn Sie die erste Zeile in 'python - << 'END' ändern, wäre die Ausgabe' $ SHELL'. Wenn Sie vorhandenen Code kopieren und einfügen, um ihn in ein Bash-Skript einzubetten, möchten Sie höchstwahrscheinlich keine Shell-Ersetzungen - Sie möchten, dass der Code genauso ausgeführt wird, wenn er nicht in ein Bash-Skript eingebettet ist, oder? –

33

Warum sollten Sie -c verwenden? Dies funktioniert für mich:

python << END 
... code ... 
END 

ohne etwas extra zu brauchen.

+2

Um Ausgabe in eine Variable zu sammeln, habe ich 'ABC = $ (python << END' ...' END) 'und es hat funktioniert. –

+0

Was ist, wenn wir mit Python einen String-Parameter aus Bash-Skript kommunizieren wollen? –

+0

Dann brauchst du das '-', wie in Neds Antwort. Die Argumente würden dem Strich folgen. –

2

Interessant ... Ich will eine Antwort jetzt auch ;-)

Er ist nicht zu fragen, wie Python-Code in einem Bash-Skript auszuführen, aber tatsächlich habe das Python-Set Umgebungsvariablen.

Setzen Sie dies in ein Bash-Skript und versuchen Sie es zu sagen "es hat funktioniert".

Das Problem ist, dass das Python in einer Kopie der Umgebung ausgeführt wird. Alle Änderungen an dieser Umgebung werden nach dem Beenden von Python nicht angezeigt.

Wenn es eine Lösung dafür gibt, würde ich es auch gerne sehen.

+1

Das ist nicht wirklich, was ich unbedingt bekommen würde, und ich bin ziemlich sicher, dass Sie nicht Umgebungsvariablen von einem Kindprozess (direkt) erhalten oder die Umgebungsvariablen eines Elternteils (direkt) ändern können. Sie können jedoch die Ausgabe des Python-Skripts im Bash-Skript "auswerten" und so beliebige Anweisungen ausführen, Umgebungsvariablen setzen oder alles andere tun, was Ihnen gefällt. –

+1

@Eric: Wenn du wirklich eine Antwort willst, poste deine eigene Frage. –

+0

Matt, Entschuldigung ... Ich habe kurz auf dein Python-Skript geschaut und gesehen, dass du mit os.environ Sachen machst und angenommen, dass das genau das war, was du getan hast. Mein Fehler. –

7

Wenn Sie die Ausgabe der Python in der Bash-Skript verwenden möchten, können Sie etwas tun:

#!/bin/bash 

ASDF="it didn't work" 

ASDF=`python <<END 
ASDF = 'it worked' 
print ASDF 
END` 

echo $ASDF 
+1

Seien Sie vorsichtig, wie Sie den Heredoc-Marker benennen. Wenn es wie in Ihrem Beispiel nicht angegeben ist, wird die Shell-Erweiterung innerhalb der heredoc-Zeichenfolge ausgeführt. Wenn dein Python-Code zum Beispiel nur 'print '$ SHELL'' wäre, wäre die Ausgabe'/bin/bash' oder was auch immer deine Shell ist. Wenn Sie die erste Zeile in 'python - << 'END' ändern, wäre die Ausgabe' $ SHELL'. Wenn Sie vorhandenen Code kopieren und einfügen, um ihn in ein Bash-Skript einzubetten, möchten Sie höchstwahrscheinlich keine Shell-Ersetzungen - Sie möchten, dass der Code genauso ausgeführt wird, wenn er nicht in ein Bash-Skript eingebettet ist, oder? –

+0

Sie haben Recht. Danke Chris! – desgua

0

Wenn Sie zsh verwenden, können Sie Python im Skript einbetten mit zsh der join und Python stdin Option (python -):

py_cmd=${(j:\n:)"${(f)$(
    # You can also add comments, as long as you balance quotes 
    <<<'if var == "quoted text":' 
    <<<' print "great!"')}"} 

catch_output=$(echo $py_cmd | python -) 

Sie können den Python-Schnipsel, einrücken, so sieht es schöner als die EOF oder <<END Lösungen, wenn innerhalb von Funktionen.

5

Manchmal ist es keine gute Idee, hier Dokument zu verwenden.Eine weitere Alternative ist python -c zu verwenden:

py_script=" 
import xml.etree.cElementTree as ET,sys 
... 
" 

python -c "$py_script" arg1 arg2 ... 
+0

Schön und einfach, und Sie können den Python-Code aus der Mitte des Rests des Bash-Codes verschieben. Lässt auch Ihren Python-Code von stdin lesen. – dbort

5

Ein Problem bei der Verwendung von bash here document ist, dass das Skript dann Python auf stdin übergeben wird, also wenn Sie das Python-Skript als Filter verwenden möchten, ist es unhandlich wird . Eine Alternative ist die bash ‚s process substitution, so etwas zu verwenden:

... | python <(echo ' 
code here 
') | ... 

Wenn das Skript es zu lange, können Sie auch here document innerhalb des paren, wie diese verwenden:

... | python <(
cat << END 
code here 
END 
) | ... 

Inside the Skript, können Sie lesen/schreiben, wie Sie normalerweise von/zu Standard-I/O (zB sys.stdin.readlines, um alle Eingabe verschlingen).

Auch python -c können auch in anderen Antworten, wie erwähnt verwendet werden, aber hier ist, wie ich es tun gut zu formatieren, unter Wahrung der Regeln Einzug des Python noch (credits):

read -r -d '' script <<-"EOF" 
    code goes here prefixed by hard tab 
EOF 
python -c $script 

nur sicherstellen, dass Das erste Zeichen jeder Zeile in diesem Dokument ist eine harte Registerkarte. Wenn Sie dies in einer Funktion setzen, dann benutze ich die folgenden Trick, den ich irgendwo gesehen, um es ausgerichtet aussehen:

function somefunc() { 
    read -r -d '' script <<-"----EOF" 
     code goes here prefixed by hard tab 
----EOF 
    python -c $script 
} 
+1

Warum 0 upvotes? Es ist die einzige richtige Antwort hier, wenn Sie sys.stdin in Ihrem Programm verwenden möchten! –

+0

Dies ist die beste Lösung, upvote es! – user1171968

3

Ready to copy-paste Beispiel mit Eingang:

input="hello" 
output=`python <<END 
print "$input world"; 
END` 

echo $output 
-1

Try dies:

#!/bin/bash 
a="test" 
python -c "print '$a this is a test'.title()" 
Verwandte Themen