Python -C vs Python -<< Heredoc



我试图在Bash脚本中运行一些Python代码,所以我想了解它们之间的区别:

#!/bin/bash
#your bash code
python -c "
#your py code
"

python - <<DOC
#your py code
DOC

我在网上查了一下,但无法编译有关该主题的内容。你认为哪一个比另一个好?如果你想从Python代码块返回一个值到你的Bash脚本,那么heredoc是唯一的方法吗?

使用here文档的主要缺陷是脚本的标准输入将是here文档。所以如果你有一个脚本想要处理它的标准输入,python -c几乎是你唯一的选择。

另一方面,使用python -c '...'绑定了shell需要的单引号,所以你只能在Python脚本中使用双引号字符串;使用双引号来保护脚本不受shell的攻击会带来额外的问题(双引号中的字符串经历各种替换,而单引号的字符串在shell中是文字)。

作为题外话,请注意您可能也需要对此处文档分隔符单引号,否则Python脚本会受到类似替换的影响。
python - <<'____HERE'
print("""Look, we can have double quotes!""")
print('And single quotes! And `back ticks`!')
print("$(and what looks to the shell like process substitutions and $variables!)")
____HERE

作为另一种选择,转义分隔符的工作原理相同,如果您喜欢(python - <<____HERE)

如果您正在使用bash,那么如果您应用更多的样板文件,就可以避免以下问题:

python <(cat <<EoF
name = input()
print(f'hello, {name}!')
EoF
)

这将允许您在不放弃标准输入的情况下运行嵌入的Python脚本。开销与使用cmda | cmdb基本相同。这种技术被称为过程替换。

如果希望能够以某种方式验证脚本,我建议您将其转储到临时文件:

#!/bin/bash
temp_file=$(mktemp my_generated_python_script.XXXXXX.py)
cat > $temp_file <<EoF
# embedded python script
EoF
python3 $temp_file && rm $temp_file

如果脚本运行失败,将保留脚本

如果您希望使用python -c '...'而不需要用双引号转义,您可以首先使用here-documents:

将代码加载到bash变量中。
read -r -d '' CMD << '--END'
print ("'quoted'")
--END
python -c "$CMD"

python代码被逐字加载到CMD变量中,不需要转义双引号。

如何使用这里的文档与输入

tripleee的答案包含了所有的细节,但是有一些Unix技巧可以解决这个限制:

所以如果你有一个脚本想要处理它的标准输入,python -c几乎是你唯一的选择。

这个技巧适用于所有想要从重定向的stdin(例如,./script.py < myinputs)和读取用户输入的程序:

python - <<'____HERE'
import os
os.dup2(1, 0)
print(input("--> "))
____HERE

运行此工作:

$ bash heredocpy.sh
--> Hello World!
Hello World!

如果您想获得原始stdin,请先运行os.dup(0)。下面是一个真实世界的例子:


这是有效的,因为只要stdout或stderr是tty,就可以从它们中读取和写入它们。(否则,您可以打开/dev/tty。这就是less所做的。)

如果您想处理来自文件的输入,这也是可能的——您只需要使用新的fd:

文件

示例
cat <<'____HERE' > file.txt
With software there are only two possibilites:
either the users control the programme
or the programme controls the users.
____HERE
python - <<'____HERE' 4< file.txt
import os
for line in os.fdopen(4):
  print(line.rstrip().upper())
____HERE

命令示例

不幸的是,管道在这里不起作用——但是过程替换可以:

python - <<'____HERE' 4< <(fortune)
import os
for line in os.fdopen(4):
  print(line.rstrip().upper())
____HERE

相关内容

  • 没有找到相关文章

最新更新