2010-02-03 24 views
37

Me gustaría insertar el texto de los scripts cortos de python dentro de un script bash, para usar en decir, mi .bash_profile. ¿Cuál es la mejor manera de hacer tal cosa?incrustando scripts cortos de python dentro de un script bash

La solución que tengo hasta ahora es llamar al intérprete de Python con la opción -c, y decirle al intérprete que exec lo lea desde stdin. A partir de ahí, puedo construir herramientas simples como la siguiente, lo que me permite procesar el texto para su uso en mi modo interactivo:

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

Este enfoque huele un poco gracioso para mí, sin embargo, y me pregunto qué alternativas a hacerlo de esta manera podría ser.

Mis habilidades de guion bash son bastante rudimentarias, por lo que estoy particularmente interesado en saber si estoy haciendo algo tonto desde la perspectiva del intérprete bash.

+0

¿Puedes decir más claramente qué es lo que en realidad estás tratando de hacer? por lo que veo, Python no es realmente necesario. puedes hacer la mayoría de las cosas con el caparazón. – ghostdog74

+1

@ ghostdog74: nada realmente más profundo de lo que estaba diciendo; Solo soy un programador de python mucho mejor que un programador de bash, y el python IMO es más poderoso, en general, que bash. Puede ser útil implementar la funcionalidad utilizada en un script bash en python, y algunas veces no depender de archivos externos al hacerlo. Finalmente estoy haciendo el cambio de tcsh a bash (después de 15 años), y estoy tratando de doblar el caparazón a mi voluntad/preferencias. –

+0

-1: ¿Por qué no simplemente crear un archivo de módulo .py? ¿Por qué forzar Python en un script de shell cuando una mejor solución es (por lo general) para dejar de usar el shell por completo? –

Respuesta

27

el intérprete de Python acepta - en la línea de comandos como sinónimo de stdin para que pueda reemplazar las llamadas a pyexec con:

python - <<END 

, ver datos de línea de comandos here.

+1

Huh - Hice una búsqueda de texto en la página man de python, y el texto 'stdin' no está allí. Mirando más de cerca, la "entrada estándar" sí lo es. Doh. –

+0

De acuerdo en que el enfoque heredoc puede funcionar.Sin embargo, hay que tener cuidado con las cosas: (1) si el marcador heredoc ('END' en el ejemplo de Ned) aparece en la columna 0 en el script de Python, el heredoc terminará temprano; (2) las variaciones en el marcador heredoc (con o sin '-') afectan si las pestañas y los espacios se conservan; y (3) superposición sintáctica entre Python y bash cuando se activa la expansión variable (el marcador heredoc no se cita), p. '$ {1}' podría aparecer legítimamente en un especificador de formato de cadena Python, pero sería reemplazado por un parámetro de línea de comando bash si el marcador heredoc no está citado. –

+1

Tenga cuidado de cómo nombra el marcador heredoc. Cuando no está citado como en su ejemplo, la expansión del shell se producirá dentro de la cadena heredoc. Por ejemplo, si su código python consistía en 'print '$ SHELL'', la salida sería'/bin/bash' o lo que sea que sea su caparazón. Si cambia la primera línea a 'python - << 'END'', la salida sería' $ SHELL'. Si está copiando y pegando código existente para incrustarlo en un script bash, casi seguro que no quiere sustituciones de shell; quiere que el código se ejecute de la misma manera que cuando no está incrustado en un script bash, ¿verdad? –

33

¿Por qué debería necesitar usar -c? Esto funciona para mí:

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

sin necesidad de ningún extra.

+2

Para recopilar resultados en una variable, hice 'ABC = $ (python << END' ...' END) 'y funcionó. –

+0

¿Qué sucede si queremos comunicar a python un parámetro de cadena proveniente de script bash? –

+0

Entonces necesitas el '-', como en la respuesta de Ned. Los argumentos seguirían el guión. –

2

Interesante ... quiero una respuesta ahora también ;-)

Él no está pidiendo la manera de ejecutar código Python dentro de una escritura del golpe pero en realidad tienen las variables de entorno establecidas pitón.

Pon esto en un script bash e intenta que diga "funcionó".

El problema es que el python se ejecuta en una copia del entorno. Cualquier cambio en ese entorno no se ve después de las salidas de Python.

Si hay una solución para esto, me encantaría verlo también.

+1

Eso no es realmente lo que estaba obteniendo necesariamente, y estoy bastante seguro de que no puede obtener variables de entorno de un proceso hijo (directamente) o alterar las variables de entorno de un padre (directamente). Usted * puede * sin embargo 'eval' la salida de la secuencia de comandos python en la secuencia de comandos bash, por lo tanto, la ejecución de las declaraciones arbitrarias, la configuración de variables de entorno o hacer cualquier otra cosa que le pueda gustar. –

+1

@Eric: si realmente quiere una respuesta, publique su propia pregunta. –

+0

Matt, lo siento ... Miré brevemente el script de Python y vi que estabas haciendo cosas con os.environ y asumí que ese era el tipo de cosa que estabas haciendo. Mi error. –

7

Si es necesario utilizar la salida del pitón en la escritura del golpe que se puede hacer algo como esto:

#!/bin/bash 

ASDF="it didn't work" 

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

echo $ASDF 
+1

Tenga cuidado de cómo nombra el marcador heredoc. Cuando no está citado como en su ejemplo, la expansión del shell se producirá dentro de la cadena heredoc. Por ejemplo, si su código python consistía en 'print '$ SHELL'', la salida sería'/bin/bash' o lo que sea que sea su caparazón. Si cambia la primera línea a 'python - << 'END'', la salida sería' $ SHELL'. Si está copiando y pegando código existente para incrustarlo en un script bash, casi seguro que no quiere sustituciones de shell; quiere que el código se ejecute de la misma manera que cuando no está incrustado en un script bash, ¿verdad? –

+0

Tienes razón. ¡Gracias, Chris! – desgua

0

Si está utilizando zsh puede incrustar Python dentro de la secuencia de comandos mediante la entrada estándar join y pitón de zsh opción (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 -) 

Usted puede sangrar el fragmento de Python, por lo que se ve mejor que en las EOF o <<END soluciones cuando las funciones dentro.

5

A veces no es una buena idea usar aquí el documento.Otra alternativa es utilizar pitón -c:

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

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

Agradable y simple, y le permite mover el código python lejos del centro del resto del código bash. También permite que su código python lea de stdin. – dbort

5

Un problema con el uso de bash here document es que el script se pasa a Python en stdin, por lo que si desea utilizar la secuencia de comandos de Python como un filtro, se hace difícil de manejar . Una alternativa es utilizar el bash 's process substitution, algo como esto:

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

Si el guión es demasiado largo, se podría también utilizar here document dentro el paren, así:

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

Dentro de la secuencia de comandos, puede leer/escribir como lo haría normalmente desde/hasta la E/S estándar (por ejemplo, sys.stdin.readlines para engullir toda la entrada).

Además, python -c se puede utilizar como se ha mencionado en otras respuestas, pero aquí es como me gusta hacerlo para dar formato muy bien, sin dejar de respetar las reglas de Python sangría (credits):

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

Sólo asegúrese de que el primer caracter de cada línea dentro de este documento es una pestaña dura. Si usted tiene que poner esto dentro de una función, entonces utilizar el siguiente truco que vi en algún lugar para que se vea alineado:

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

¿Por qué 0 votos ascendentes? ¡Es la única respuesta correcta aquí, si quieres usar sys.stdin en tu programa! –

+0

¡Esta es la mejor solución, hasta la fecha! – user1171968

3

Lista para copiar y pegar ejemplo, con la entrada:

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

echo $output 
-1

Try esto:

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