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

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

この答えターミナルのコマンドラインから複数行の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. bash スクリプトで python サブスクリプトの出力を収集するにはどうすればよいですか? (たとえば、 などの変数内$output)。

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

答え1

Pythonに変数を取得する

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

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

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

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
)

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

答え2

このアプローチの問題点は、埋め込まれた 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
)

答え3

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

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
)

答え4

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

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

関連情報