Código híbrido en scripts de shell. Compartir variables

Código híbrido en scripts de shell. Compartir variables

esta respuestaanaliza cómo ejecutar un fragmento de Python de varias líneas desde la línea de comando en una terminal. Noté que la respuesta funciona muy bien dentro de los scripts de Shell, incluso con sangría anidada, lo cual es muy bueno, por ejemplo

#!/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

huellas dactilares:

0 
hello
hello
1
hello
hello
2
hello
hello

Sin embargo, me resulta difícil compartir variables entre el script de shell y el fragmento de Python.

  1. ¿Cómo puedo recopilar la salida del subíndice de Python en el script bash? (por ejemplo, en una variable como $output).

  2. ¿Cómo puedo pasar una variable bash (por ejemplo $some_text) al script de Python?

Respuesta1

Obtener una variable para Python

Dado que (cuando el EOFmarcador no está entre comillas) la sustitución de variables se produce antes de que el texto pase del heredoc a pythonla entrada estándar, puede incluir la variable directamente en el script.

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

Si some_textfuera así test, Python lo vería some_text = "test". Sin embargo, tenga en cuenta que puede verse como una vulnerabilidad de inyección de código. Si some_textfuera "; import os; os.system("evil-command"); x = ", por ejemplo, Python vería:

some_text = ""; import os; os.system("evil-command"); x = ""

y ejecutar ese comando malvado.

Si desea poder incorporar su código Python directamente a un script sin modificaciones, puede exportar su variable.

export some_text

y utilizar os.environpara recuperarlo.

some_text = os.environ['some_text']

Ese es un enfoque mucho más sensato y seguro.


Obtener resultados de Python

Puede utilizar la sustitución de comandos para recopilar la salida del script.

output=$(
python - <<EOF
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

(tenga en cuenta que se eliminan todos los caracteres de nueva línea finales)

Respuesta2

El problema con su enfoque es que el script Python incorporado ya no tiene acceso a la entrada estándar original (ya que su entrada estándar es... ella misma).

Si eso es un problema, puedes escribir:

python -c '
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
'

O si el script de Python puede contener comillas simples:

python -c "$(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)"

O:

python <(cat << 'EOF'
import sys;
for r in range(3):
  print r
  for a in range(2):
    print "hello"
EOF
)

Respuesta3

Utilice un guión como nombre de archivo:

ruby - a b <<'END'
puts ARGV.join(",")
END

python - a b <<'END'
import sys
print ",".join(sys.argv[1:])
END

No sé si sys.argv[1:]es la forma correcta de hacer esto en Python. Para -e/-c puedes especificar el final de los argumentos con --:

set -- -a -b -c
ruby -e 'puts ARGV.join(",")' -- "$@"
python -c 'import sys; print ",".join(sys.argv[2:])' -- "$@"

Capturando resultados y redirigiendo STDERR:

x=$(ruby <<'END' 2> /dev/null
puts "a"
abort "b"
END
)

Respuesta4

1) Puede escribir asignaciones de variables a un archivo en Python y luego obtenerlo en su script bash.

2) Dado que su palabra (EOF) no está entre comillas, todas las líneas del documento aquí están sujetas a expansión de parámetros. Puedes usar esto para pasar cosas al script de Python.

información relacionada