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.
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 .
Pourquoi devriez-vous avoir besoin d'utiliser -c
? Cela fonctionne pour moi:
python << END
... code ...
END
sans avoir besoin de rien d'extra.
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
}
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
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 ...
Prêt à copier-coller exemple avec entrée:
input="hello"
output=`python <<END
print "$input world";
END`
echo $output
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.
Essaye ça :
#!/bin/bash
a="test"
python -c "print '$a this is a test'.title()"
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.