如何在bash中传递字符串参数并维护该字符串?
我正在为bash中的一个命令制作一个包装器脚本,我希望传递带有空格的字符串参数,同时将其作为字符串保存在bash文件中 我看到过许多问题,这些问题涉及将字符串作为一项传递给bash脚本,而不是在脚本中使用时如何维护字符串 我还尝试了许多不同的引用和转义字符的方法,看看是否有什么不同 我的脚本布局的一个例子是如何在bash中传递字符串参数并维护该字符串?,bash,Bash,我正在为bash中的一个命令制作一个包装器脚本,我希望传递带有空格的字符串参数,同时将其作为字符串保存在bash文件中 我看到过许多问题,这些问题涉及将字符串作为一项传递给bash脚本,而不是在脚本中使用时如何维护字符串 我还尝试了许多不同的引用和转义字符的方法,看看是否有什么不同 我的脚本布局的一个例子是 #/usr/bin/env bash exec my_程序/path/to/code.py“${@}” 当我执行my_script-arg“A string”时,所需的行为是将包装好的命令
#/usr/bin/env bash
exec my_程序/path/to/code.py“${@}”
当我执行my_script-arg“A string”
时,所需的行为是将包装好的命令作为my_program/path/to/code.py-arg“A string”
执行,但它作为my_program/path/to/code.py-arg A string
运行,从而导致错误:无法识别的参数:string
是否有某种方法可以确保,当传递字符串时,它会一直保持该字符串
一个最小、完整且可验证的示例:
bash_strings.sh
echo“${@}”
输出
$bash bash\u strings.sh——测试“字符串”
--测试字符串
Bash将删除引号。您必须再次插入它们。但是,如果在包装器中转义引号,则每个参数都将在引号中进行解释:
exec my_program /path/to/code.py \"${@}\"
将成为
my_program /path/to/code.py "-arg A string"
你也不想要
我认为最好的方法是,如果您的包装器适用于特定的程序,则使用不同的标志执行一个案例
,如:
while getopts "arg:r:v" arg; do
case "$arg" in
arg)
exec my_program /path/to/code.py -arg $OPTARG
;;
r)
exec my_program /path/to/code.py -r $OPTARG
;;
v)
exec my_program /path/to/code.py -v $OPTARG
;;
esac
done
编辑为OP,为了清晰起见,对问题进行了编辑
如果您将输入更改为:
bash bash_strings.sh --test "\"A String\""
对于这个具体的例子,它会起作用。Bash正在那里的某个地方删除引用 你的bash_strings.sh
有缺陷,因为echo“$@”
会丢弃数据(使/yourscript“hello world”
看起来与/yourscript“hello”“world”
完全相同)。要准确反映命令的参数列表,请使用printf%q
生成引用版本,如下所示:
#!/usr/bin/env bash
(( $# )) || exit
printf '%q ' "$@"; echo
…对于/bash\u字符串--测试“字符串”
,将作为输出发出:
--test 'A string'
…或者,可能是不同的语义相同的表示,例如:
--test A\ string
…无论哪种方式,都反映了原始引用是真实传递的。如果bash解析了一个字符串,它将一个字符串保持为单个数组元素,因此它正确地成为Python中sys.argv
中的单个元素。这正是应该发生的事情。您键入的引号是bash语法告诉bash保持项目在一起,而不是字符串本身的一部分。您的问题的前提是错误的<代码>“$@”
正是将“字符串”
保留为单个单词所需要的。如果它被分成两个词,它发生在其他地方,我们需要看到一个例子来说明这个问题。您发布的脚本也很好,就像在Python中使用subprocess.Popen(['someprogram','foo bar')
——您不希望foo bar
周围的三个引号成为运行的命令的一部分,对吗?在bash中也是如此;语法引号(与文字引号相反)是在解析时使用的,而不是传递给被调用的程序。你是说我不应该期望在输出中看到引号,因为它与python打印(“字符串”)的方式类似吗?如果是这样,我明白你的意思。在Popen的情况下,我可能会传递字符串的repr,或者““foo bar“
以便获得所需的结果。在这种情况下,我不知道如何在bash中实现这一点。($)&&printf'-%s\n'$@“
是另一种获取命令行参数列表的简单方法,它不会混淆它们的开始和结束位置。在bash中运行“字符串”
时,引号是bash语法的一部分,而不是命令的一部分。它们不在sys.argv
@CharlesDuffy中是完全正确的。我不太清楚你在说什么。我是说OP的原始代码已经有了有效的语法引号,导致参数列表被逐字传递,添加文字引号是有害的,而不是有益的……事实上,“$”
在第一个参数之前加上一个“
”
”
,在最后一个参数之后加上一个“
”,但是其他参数没有修改,因此/yourprogram“foo-bar”“baz-qux”“third-arg”
变成[“foo-bar”,“baz-qux”,“third-arg”],,带有“
添加在foo
之前,另一个添加在最后的arg
之后。我很难看出这是一个有用或有价值的结果。如果他的my_程序
以某种方式扭曲了参数,这可能会有用。这个问题是echo
固有的。例如,请注意,echo--test“A String”
,echo--test A String
,和echo--test A String”
都打印完全相同的内容。(但是对相同的参数列表使用printf“%q”
将使差异变得更清楚。)编辑以使其更清楚;非常感谢。(因为这个答案被标记为社区维基,所以也可以自己跳进去编辑它)。