为啥这个带有 shebang #!/bin/sh 和 exec python 的片段在 4 个单引号内起作用?

Posted

技术标签:

【中文标题】为啥这个带有 shebang #!/bin/sh 和 exec python 的片段在 4 个单引号内起作用?【英文标题】:Why does this snippet with a shebang #!/bin/sh and exec python inside 4 single quotes work?为什么这个带有 shebang #!/bin/sh 和 exec python 的片段在 4 个单引号内起作用? 【发布时间】:2013-07-01 18:21:41 【问题描述】:

我试图理解这个问题的答案之一:

Cannot pass an argument to python with "#!/usr/bin/env python"

#!/bin/sh
''''exec python -u -- "$0" $1+"$@" # '''

这很好用,但我不明白为什么它在该行的开头使用四个刻度而不是三个。

另外,为什么散列在字符串的末尾附近?

【问题讨论】:

请注意,这将在$PATH 中启动any python,因此与#!/usr/bin/env -i python 相比,它非常不安全 >(更好)知道并使用完整路径:#!/usr/bin/python. 【参考方案1】:

Python 支持三引号字符串:

'''something'''

Shell 仅支持单引号字符串:

'something'

通过使用 四个 引号,sh 将其视为 2 个空字符串,但 Python 将前三个视为三引号字符串的开头,并将第四个包含为字符串的一部分价值。

该行的其余部分随后被 sh 解释为命令,但被 Python 解释为字符串的一部分。

#sh 而言随后形成一个注释,但它仍然是 Python 的字符串,用一个结束的三引号将其关闭。

所以,总结一下:

sh 看到:空字符串 ('') - 空字符串 ('') - 命令 (exec python -u -- "$0" $1+"$@") - 评论 (# ''') Python 看到:三引号字符串文字(包含字符 'exec python -u -- "$0" $1+"$@" #

所以sh 执行该命令,将其自身替换为带有脚本名称和其余命令行参数的python -u --,Python 读取此文件并只看到一个不会去任何地方的初始字符串文字。

因为它是文件中的第一个字符串文字,它将被设置为 __main__ 模块的文档字符串,但如果这是主脚本,这几乎没有关系。

【讨论】:

什么是$1+"$@"?它与$@ 有何不同? @Dog:这意味着:如果参数1被设置,替换"$@"(引用参数)否则替换为null。 您可以在 Python 中动态地进行操作。不过当时并没有什么意义。 Here 是$1+"$@" 的更多上下文。所以在很多情况下"$@" 本身就可以正常工作。 所以总而言之,这个技巧是使用python的模块文档字符串首先运行一个迷你shell脚本。【参考方案2】:

我只是使用:

#!/bin/sh
''':'
exec python -tt "$0" "$@"
'''
# The above shell shabang trick is more portable than /usr/bin/env and supports adding arguments to the interpreter (python -tt)

【讨论】:

与接受的答案相比,使用您的解决方案有什么优势? 这并不能回答发布的问题,无论 使用什么,OP 都想了解特定代码的工作原理。

以上是关于为啥这个带有 shebang #!/bin/sh 和 exec python 的片段在 4 个单引号内起作用?的主要内容,如果未能解决你的问题,请参考以下文章

shell基本语法和命令

为啥在传递引用的参数时会得到“/bin/sh:参数列表太长”?

如何使用带有 shebang 的 awk 的多个参数(即#!)?

为啥我收到错误“/bin/sh: x86_64-apple-darwin13.4.0-clang: command not found”?

为啥我的 .gitlab-ci.yml 在纱线测试中不断失败,并出现错误“/bin/sh: 1: react-scripts: not found”?

我应该使用 hashbang/shebang 吗?