web-dev-qa-db-fra.com

incorporer de courts scripts python dans un script bash

J'aimerais incorporer le texte de courts scripts python dans un script bash, pour l'utiliser dans, par exemple, mon .bash_profile. Quelle est la meilleure façon de faire une telle chose?

La solution que j’ai jusqu’à présent consiste à appeler l’interpréteur python avec l’option -c et à lui indiquer exec quelle que soit sa valeur dans stdin. À partir de là, je peux créer des outils simples comme ceux-ci, me permettant de traiter du texte pour l'utiliser dans mon invite interactif:

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)] % "

Cette approche sent cependant un peu drôle pour moi, et je me demande quelles solutions de rechange pour le faire de cette façon pourraient être. 

Mes compétences en script bash sont plutôt rudimentaires, donc je suis particulièrement intéressé à savoir si je fais quelque chose de stupide du point de vue de l'interprète bash.

45
Matt Anderson

L'interpréteur python accepte - sur la ligne de commande comme synonyme de stdin afin de pouvoir remplacer les appels à pyexec par:

python - <<END

Voir la référence de ligne de commande ici .

29
Ned Deily

Pourquoi devriez-vous avoir besoin d'utiliser -c? Cela fonctionne pour moi:

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

sans avoir besoin de rien d'extra.

39
Ricardo Cárdenes

Un problème lié à l'utilisation de bash here document est que le script est ensuite transmis à Python le stdin. Par conséquent, si vous souhaitez utiliser le script Python en tant que filtre, il devient difficile à manier. Une alternative consiste à utiliser le process substitution de la bash, comme ceci:

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

Si le script est trop long, vous pouvez aussi utiliser here document à l'intérieur du paren, comme ceci:

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

Dans le script, vous pouvez lire/écrire comme vous le feriez normalement depuis/vers une entrée/sortie standard (par exemple, sys.stdin.readlines pour engloutir toutes les entrées).

De plus, python -c peut être utilisé comme mentionné dans d'autres réponses, mais voici comment j'aime bien le faire pour formater correctement, tout en respectant les règles d'indentation de Python ( crédits ):

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

Assurez-vous simplement que le premier caractère de chaque ligne du document est un onglet rigide. Si vous devez mettre cela dans une fonction, alors j'utilise l'astuce ci-dessous que j'ai vue quelque part pour lui donner un aspect aligné:

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

Si vous devez utiliser la sortie du python dans le script bash, vous pouvez faire quelque chose comme ceci: 

#!/bin/bash

ASDF="it didn't work"

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

echo $ASDF
7
desgua

Parfois, ce n’est pas une bonne idée d’utiliser ce document. Une autre alternative consiste à utiliser python -c:

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

python -c "$py_script" arg1 arg2 ...
7
Don Li

Prêt à copier-coller exemple avec entrée:

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

echo $output
5
Adrian Lopez

Intéressant ... Je veux aussi une réponse maintenant ;-)

Il ne demande pas comment exécuter du code python dans un script bash, mais dispose en réalité des variables d'environnement de jeu python.

Mettez ceci dans un script bash et essayez de le faire dire "ça a marché".

export ASDF="it didn't work"

python <<END
import os
os.environ['ASDF'] = 'it worked'
END

echo $ASDF

Le problème est que le python est exécuté dans une copie de l'environnement. Aucune modification apportée à cet environnement ne sera visible après la sortie de python.

S'il y a une solution à cela, j'aimerais aussi la voir.

2
eric.frederich

Essaye ça : 

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

Si vous utilisez zsh, vous pouvez incorporer Python dans le script à l'aide de l'option join et de python stdin de zsh (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 -)

Vous pouvez mettre en retrait l'extrait de code Python afin qu'il soit plus esthétique que les solutions EOF ou <<END dans les fonctions.

0
fedeDev