Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在bash中传递字符串参数并维护该字符串?_Bash - Fatal编程技术网

如何在bash中传递字符串参数并维护该字符串?

如何在bash中传递字符串参数并维护该字符串?,bash,Bash,我正在为bash中的一个命令制作一个包装器脚本,我希望传递带有空格的字符串参数,同时将其作为字符串保存在bash文件中 我看到过许多问题,这些问题涉及将字符串作为一项传递给bash脚本,而不是在脚本中使用时如何维护字符串 我还尝试了许多不同的引用和转义字符的方法,看看是否有什么不同 我的脚本布局的一个例子是 #/usr/bin/env bash exec my_程序/path/to/code.py“${@}” 当我执行my_script-arg“A string”时,所需的行为是将包装好的命令

我正在为bash中的一个命令制作一个包装器脚本,我希望传递带有空格的字符串参数,同时将其作为字符串保存在bash文件中

我看到过许多问题,这些问题涉及将字符串作为一项传递给bash脚本,而不是在脚本中使用时如何维护字符串

我还尝试了许多不同的引用和转义字符的方法,看看是否有什么不同

我的脚本布局的一个例子是

#/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”
将使差异变得更清楚。)编辑以使其更清楚;非常感谢。(因为这个答案被标记为社区维基,所以也可以自己跳进去编辑它)。