シェルスクリプト内のハイブリッドコード。変数の共有


10

この回答では、ターミナルのコマンドラインから複数行のPythonスニペットを実行する方法について説明します。入れ子になったインデントがあっても、答えはシェルスクリプト内でうまく機能することに気づきました。

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

プリント:

0 
hello
hello
1
hello
hello
2
hello
hello

ただし、シェルスクリプトとPythonスニペットの間で変数を共有するのに苦労しています。

  1. python添え字の出力をbashスクリプトで収集するにはどうすればよいですか?(例:などの変数内$output)。

  2. $some_textPythonスクリプトにbash変数(など)を渡すにはどうすればよいですか?


1
python - <<EOF代わりに行うことができます。

jftr imoこれは悪いスタイルです。それを避けるようにしてください
Ulrich Dangel 2013

1
なぜ/ zshタグなのですか?
ステファンChazelas

回答:


12

Pythonへの変数の取得

EOFマーカーが引用符で囲まれていない場合)ヒアドキュメントからpythonの標準入力にテキストが渡される前に変数置換が行われるため、変数をスクリプトで直接スローできます。

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

場合some_textだったtest、Pythonは見るであろうsome_text = "test"。ただし、コードインジェクションの脆弱性と見なされる可能性があることに注意してください。場合some_textした"; import os; os.system("evil-command"); x = "、例えば、Pythonは見るでしょう:

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

その邪悪なコマンドを実行します。

変更を加えずにPythonコードをスクリプトに直接挿入できるようにしたい場合は、変数をエクスポートできます。

export some_text

それos.environを取得するために使用します。

some_text = os.environ['some_text']

これは、より安全で安全な方法です。


Pythonからの出力の取得

コマンド置換を使用して、スクリプトの出力を収集できます。

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

(末尾の改行文字はすべて削除されることに注意してください)


これは素晴らしいですね。と言ったときに"You could also pass the variable to the script as an argument"、Pythonスクリプトがシェルスクリプト内に埋め込まれていることを考慮して、どうしますか
Amelio Vazquez-Reina

すみません、それを一瞬忘れてしまいました。そのソリューションを削除して、より良いソリューションを追加しました。

ヒアドキュメントマーカーの命名方法に注意してください。あなたの例のように引用符で囲まれていない場合、ヒアドキュメント文字列内でシェル展開が発生します。たとえば、Pythonコードがのみprint '$SHELL'で構成されている場合、出力は/bin/bashシェルで発生するものになります。最初の行をに変更するpython - <<'END'と、出力はになります$SHELL。既存のコードをコピーして貼り付けてbashスクリプトに埋め込む場合、ほとんどの場合、シェルの置換は必要ありません。bashスクリプトに埋め込まれていない場合と同じようにコードを実行する必要があります。
クリスジョンソン

8

あなたのアプローチの問題は、埋め込まれたpythonスクリプトが元のstdinにアクセスできないことです(そのstdinはそれ自体であるため)。

それが問題なら、あなたは書くことができます:

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

または、Pythonスクリプトに単一引用符が含まれている場合:

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

または:

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

6

ファイル名としてダッシュを使用します。

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

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

sys.argv[1:]Pythonでこれを行う正しい方法であるかどうかはわかりません。-e / -cの場合、引数の終わりを-で指定できます。

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

出力のキャプチャとSTDERRのリダイレクト:

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

2

1)Pythonでファイルに変数の割り当てを記述し、それをbashスクリプトでソースすることができます。

2)単語(EOF)は引用されていないため、ヒアドキュメントのすべての行がパラメータ展開されます。これを使用して、Pythonスクリプトにデータを渡すことができます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.