Esta respostadiscute como executar um trecho Python de várias linhas a partir da linha de comando em um terminal. Percebi que a resposta funciona muito bem em scripts de shell, mesmo com recuo aninhado, o que é muito bom, por exemplo
#!/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
impressões:
0
hello
hello
1
hello
hello
2
hello
hello
No entanto, estou tendo dificuldade em compartilhar variáveis entre o shell script e o snippet Python.
Como posso coletar a saída do subscrito python no script bash? (por exemplo, em uma variável como
$output
).Como posso passar uma variável bash (por exemplo
$some_text
) para o script Python?
Responder1
Obtendo uma variável para Python
Como (quando o EOF
marcador não está entre aspas) a substituição da variável ocorre antes do texto ser passado do heredoc para a python
entrada padrão do , você pode lançar a variável diretamente no script.
python - <<EOF
some_text = "$some_text"
EOF
Se some_text
fosse test
, python veria some_text = "test"
. Observe, entretanto, que isso pode ser visto como uma vulnerabilidade de injeção de código. Se some_text
fosse "; import os; os.system("evil-command"); x = "
, por exemplo, python veria:
some_text = ""; import os; os.system("evil-command"); x = ""
e execute esse comando maligno.
Se você quiser extrair seu código Python diretamente em um script sem nenhuma modificação, você pode exportar sua variável.
export some_text
e use os.environ
para recuperá-lo.
some_text = os.environ['some_text']
Essa é uma abordagem muito mais sensata/segura.
Obtendo saída do Python
Você pode usar a substituição de comando para coletar a saída do script.
output=$(
python - <<EOF
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
)
(observe que todos os caracteres de nova linha finais são removidos)
Responder2
O problema com sua abordagem é que o script python incorporado não tem mais acesso ao stdin original (já que seu stdin é... ele mesmo).
Se isso for um problema, você pode escrever:
python -c '
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
'
Ou se o script python puder conter aspas simples:
python -c "$(cat << 'EOF'
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
)"
Ou:
python <(cat << 'EOF'
import sys;
for r in range(3):
print r
for a in range(2):
print "hello"
EOF
)
Responder3
Use um travessão como nome do arquivo:
ruby - a b <<'END'
puts ARGV.join(",")
END
python - a b <<'END'
import sys
print ",".join(sys.argv[1:])
END
Não sei se sys.argv[1:]
é a maneira certa de fazer isso em Python. Para -e / -c você pode especificar o final dos argumentos com --:
set -- -a -b -c
ruby -e 'puts ARGV.join(",")' -- "$@"
python -c 'import sys; print ",".join(sys.argv[2:])' -- "$@"
Capturando saída e redirecionando STDERR:
x=$(ruby <<'END' 2> /dev/null
puts "a"
abort "b"
END
)
Responder4
1) Você pode escrever atribuições de variáveis em um arquivo em python e, em seguida, obtê-las em seu script bash.
2) Como sua palavra (EOF) não está entre aspas, todas as linhas do documento aqui estão sujeitas a expansão de parâmetros. Você pode usar isso para passar coisas para o script python.