我想使用脚本给出的参数 - 带引号和所有内容。到目前为止,我发现的所有解决方案都会删除引号,或者做一些微妙的不同。
我有一个工具接受字符串作为命令行参数,例如
./tool --formula="AG EF phi;"
我还有一个应该调用脚本的包装器脚本。它的调用应该是
wrap.sh ./tool --formula="AG EF phi;"
此脚本的作用类似于
# preparation phase
# ...
# call tool and remember exit code
$*
result=$?
# evaluation phase
# ...
exit $result
不幸的是,该工具被称为
./tool --formula=AG EF phi;
与上述不同,会产生语法错误。我发现的唯一黑客会给我一些像
./tool "--formula=AG EF phi;"
这也是错误的。
具体来说,这里有一些虚拟代码来举例说明问题:
首先,C程序“tool.c”。
#include <stdio.h>
int main(int argc, char** argv) {
int i;
for (i = 0; i < argc; i++) {
printf("%d: %s\n", i, argv[i]);
}
return 0;
}
然后,换行脚本“wrap.sh”:
#!/bin/bash
echo $*
$*
exit $?
现在这就是我的尝试:
$ ./tool --formula="Foo bar"
0: ./tool
1: --formula=Foo bar
$ ./wrap.sh ./tool --formula="Foo bar"
./tool --formula=Foo bar
0: ./tool
1: --formula=Foo
2: bar
$ ./wrap.sh ./tool --formula="\"Foo bar\""
./tool --formula="Foo bar"
0: ./tool
1: --formula="Foo
2: bar"
$ ./wrap.sh ./tool --formula="\"Foo bar\""
./tool --formula="Foo bar"
0: ./tool
1: --formula="Foo
2: bar"
$ ./wrap.sh "./tool --formula=\"\\\"Foo bar\\\"\""
./tool --formula="\"Foo bar\""
0: ./tool
1: --formula="\"Foo
2: bar\""
这就是我想要的(对于包装脚本中的任何必要更改):
$ ./wrap.sh ./tool --formula="Foo bar"
0: ./tool
1: --formula=Foo bar
当我转义Shabaz proposed之类的引号时,变量$*
包含正确引用的字符串,例如:
wrap.sh ./tool --formula="\"AG EF phi;\""
然后在wrap.sh
代码:
echo $*
会产生
./tool --formula="AG EF phi;"
但是,执行$*
会产生如上所述的确切错误:{“1}}的参数在”AG“之后被删除。此外,不要逃避报价会很好。
不同的shell可以帮助吗?
答案 0 :(得分:4)
请参阅BashFAQ/050(“我正在尝试将命令放在变量中,但复杂的情况总是会失败!”)。
为了保留空格并正确处理参数传递,您应该使用它来执行包装器脚本的参数:
"$@"
使用此方法,运行包装器时无需进行任何额外的引用。
$ cat ./wrap.sh
#!/bin/bash
echo "$@"
"$@"
result=$?
exit $result
$ ./wrap.sh ./tool --formula="Foo bar"
./tool --formula=Foo bar
0: ./tool
1: --formula=Foo bar
使用$@
或$*
不加引号或引用$*
会使字符串变平,这样就会将其视为一系列失去所需分组的字词。
来自man bash
:
* Expands to the positional parameters, starting from one. When
the expansion occurs within double quotes, it expands to a sin‐
gle word with the value of each parameter separated by the first
character of the IFS special variable. That is, "$*" is equiva‐
lent to "$1c$2c...", where c is the first character of the value
of the IFS variable. If IFS is unset, the parameters are sepa‐
rated by spaces. If IFS is null, the parameters are joined
without intervening separators.
@ Expands to the positional parameters, starting from one. When
the expansion occurs within double quotes, each parameter
expands to a separate word. That is, "$@" is equivalent to "$1"
"$2" ... If the double-quoted expansion occurs within a word,
the expansion of the first parameter is joined with the begin‐
ning part of the original word, and the expansion of the last
parameter is joined with the last part of the original word.
When there are no positional parameters, "$@" and $@ expand to
nothing (i.e., they are removed).
答案 1 :(得分:2)
您可以使用此脚本来保留所需的空格:
#!/bin/bash
exec bash -c "$*"
ret=$?
exit $ret
使用以下命令行执行上述脚本:
./wrap.sh ./tool --formula="\"Foo bar baz\""
0: ./tool
1: --formula=Foo bar baz
答案 2 :(得分:1)
您应该使用"
转义\
。但是,要将它们保存在一个字符串中,您应该再次将它们包含在"
中。那就是:
./tool --formula="\"AG EF phi;\""
Bash会将任意"text"
自动转换为text
作为一个单词,即使它包含空格。它像任何其他非特殊角色一样威胁逃脱角色。因此,要实际编写字符"
,您需要使用\"
。两个点的组合(使用"
将空格分隔的单词保持为一个单词并且需要输入"
本身)导致上面的行。
现在你想让你的脚本执行这一行,但是你将它作为bash本身的参数传递给脚本。因此,对特殊字符的分析和替换/删除进行两次。因此,您需要将参数传递给脚本,以便在此分析之后,它将生成上面的行。因此:
./wrap.sh "./tool --formula=\"\\\"AG EF phi;\\\"\""
注意每个"
现在变为\"
,每\
变为\\
。整个内容用引号括起来。
P.S。你可以用echo测试这个:
$ echo "a b c"
a b c
$ echo "\"a b c\""
"a b c"
$ echo "echo \"\\\"a b c\\\"\""
echo "\"a b c\""