這個答案討論如何從終端機中的命令列運行多行 Python 程式碼片段。我注意到答案在 shell 腳本中效果很好,即使有嵌套縮進,這非常好,例如
#!/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
但是,我很難在 shell 腳本和 Python 程式碼片段之間共用變數。
如何收集bash腳本中python下標的輸出? (例如,在諸如 之類的變數中
$output
)。如何將 bash 變數(例如
$some_text
)傳遞給 Python 腳本?
答案1
取得 Python 變數
由於(當EOF
標記未加引號時)變數替換發生在文字從定界符傳遞到python
的標準輸入之前,因此您可以將變數直接丟到腳本中。
python - <<EOF
some_text = "$some_text"
EOF
如果some_text
是的話test
,Python 就會看到some_text = "test"
。但請注意,它可以被視為程式碼注入漏洞。例如,如果some_text
was ,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 腳本不再能夠存取原始的標準輸入(因為它的標準輸入是...本身)。
如果這是一個問題,你可以寫:
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)沒有被引用,因此here-document的所有行都受到參數擴展。您可以使用它來將內容傳遞給 python 腳本。