我早就知道CPython的'-c'参数,(用手册上的话说)它让你 "指定[CPython]要执行的命令"。直到最近,我还认为它必须是一个单一的语句,或者至少是一行Python代码(这就排除了一些事情)。事实证明并非如此;CPython和PyPy都会接受-c的命令行参数,其中包含内嵌的换行符,就像向Unix工具(如awk)提供命令行代码的风格。
比如说。
python -c 'import sys
if len(sys.argv) > 1:
print("arguments:", sys.argv[1:])
else:
print("no arguments")' "$@"
(出于各种原因,你仍然可能想让这段代码可以导入,尽管我在这里没有这么做)。
如果你在命令行上直接提供代码,就像我在这里一样,你有一个选择 (在 Bourne shell 脚本或环境中)。 你可以用单引号引用整个代码,而不在 Python 代码中使用字面单引号,或者你可以用双引号引用,仔细地转义几个特殊字符,但得到使用单引号。如果你想避免这一切,你需要把代码放到一个 shell 变量中。
pyprog="$(cat <<'EOF'
[....]
EOF
)"
python -c "$pyprog" ...
正如你所期望的那样,命令行代码中的'__name__'就是通常的'__main__'。正如手册中所涉及的,所有进一步的命令行参数都在sys.argv中传递,sys.argv[0]设置为'-c'。 由于代码中没有文件名(通常会在sys.argv[0]中出现),这似乎是一个不错的选择,而且立即将进一步的参数传递给代码也很方便。
尽管这使得Python程序嵌入到shell脚本中成为可能,就像你可以用awk做的那样 (从而隐含地帮助实现Python作为shell脚本中的过滤器),我个人认为这个想法不太吸引人,至少对于任何实质的Python代码来说。问题不在于需要格外小心地将Python代码嵌入到你的shell脚本中,尽管这不是很好。真正的问题是,以这种方式嵌入Python代码意味着你错过了Python编程生态中的各种工具,因为它们只对独立的Python代码起作用。
(如果我不得不这样写,我很想把它开发在一个单独的文件中,由shell脚本用'python '而不是'python -c'来调用,然后只把代码嵌入shell脚本,并在最后一刻切换到'python -c ...'。)
PS:现在我知道如何做了,有点想在awk不太有我想要的功能和力量的地方尝试少量的Python代码(或者至少没有像Python那样使功能简单)。另一方面,awk不会让你考虑字符集的转换问题。 不过我可能不会用它来解析和重新格式化smartctl's JSON。那可能是足够多的代码,我想在它上面使用通常的Python工具。