在Linux上,shebang不太灵活;根据多个答案(Stephen Kitt的答案和JörgW Mittag 的答案),在shebang行中没有指定的方法来传递多个参数。
我不确定它是否对任何人都有用,但是我写了一个简短的脚本来实现缺少的功能。参见https://gist.github.com/loxaxs/7cbe84aed1c38cf18f70d8427bed1efa。
也可以编写嵌入式解决方法。在下面,我介绍了应用于相同测试脚本的四种与语言无关的变通方法,并且每一种都可以打印出结果。我想该脚本是可执行文件,位于中/tmp/shebang
。
在流程替换内部的bash heredoc中包装脚本
据我所知,这是最可靠的与语言无关的方式。它允许传递参数并保留标准输入。缺点是解释器不知道它读取的文件的(实际)位置。
#!/bin/bash
exec python3 -O <(cat << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
try:
print("input() 0 ::", input())
print("input() 1 ::", input())
except EOFError:
print("input() caused EOFError")
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
EOWRAPPER
) "$@"
调用echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
打印:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /dev/fd/62
argv[1:] :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: False
PYTHON_SCRIPT_END
请注意,进程替换会生成一个特殊文件。这可能不适合所有可执行文件。例如,#!/usr/bin/less
抱怨:/dev/fd/63 is not a regular file (use -f to see it)
我不知道是否有可能在破折号中使用heredoc进行流程替换。
将脚本包装在一个简单的heredoc中
更简短,更简单,但是您将无法stdin
从脚本中进行访问,并且它要求解释器能够从中读取和执行脚本stdin
。
#!/bin/sh
exec python3 - "$@" << 'EOWRAPPER'
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
try:
print("input() 0 ::", input())
print("input() 1 ::", input())
except EOFError:
print("input() caused EOFError")
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
EOWRAPPER
调用echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
打印:
PYTHON_SCRIPT_BEGINNING
input() caused EOFError
argv[0] :: -
argv[1:] :: ['arg1', 'arg2 contains spaces', 'arg3\\ uses\\ \\\\escapes\\\\']
__debug__ :: True
PYTHON_SCRIPT_END
使用awk system()
调用但不带参数
正确传递执行文件的名称,但是脚本不会收到您提供的参数。请注意,awk是我所知道的唯一一种语言,默认情况下两者都安装在linux上,并且默认情况下从命令行读取其指令。
#!/usr/bin/gawk BEGIN {system("python3 -O " ARGV[1])}
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
调用echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
打印:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /tmp/shebang
argv[1:] :: []
__debug__ :: False
PYTHON_SCRIPT_END
system()
如果您的参数不包含空格,请使用awk 4.1+ 调用
很好,但前提是您确定不会用包含空格的参数调用脚本。如您所见,除非对空格进行转义,否则包含空格的参数将被拆分。
#!/usr/bin/gawk @include "join"; BEGIN {system("python3 -O " join(ARGV, 1, ARGC, " "))}
print("PYTHON_SCRIPT_BEGINNING")
from sys import argv
print("input() 0 ::", input())
print("input() 1 ::", input())
print("argv[0] ::", argv[0])
print("argv[1:] ::", argv[1:])
print("__debug__ ::", __debug__)
# The -O option changes __debug__ to False
print("PYTHON_SCRIPT_END")
调用echo -e 'aa\nbb' | /tmp/shebang 'arg1' 'arg2 contains spaces' 'arg3\ uses\ \\escapes\\'
打印:
PYTHON_SCRIPT_BEGINNING
input() 0 :: aa
input() 1 :: bb
argv[0] :: /tmp/shebang
argv[1:] :: ['arg1', 'arg2', 'contains', 'spaces', 'arg3 uses \\escapes\\']
__debug__ :: False
PYTHON_SCRIPT_END
对于4.1以下的awk版本,您将必须在for循环内使用字符串连接,请参见示例函数https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html。