这个答案讨论如何从终端中的命令行运行多行 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 脚本。