我正在尝试将包含多个引用词的字符串变量替换为命令的参数。
因此,给出以下示例脚本(注意shebang中的-x,导致输出记录到stderr),
#!/bin/bash -x
myArg="\"hello\" \"world\""
echo "string is:" $myArg
exit
这给了我们,
+ myArg='"hello" "world"'
+ echo 'string is:' '"hello"' '"world"'
string is: "hello" "world"
+ exit
第二行显示实际传递给命令的内容; bash为字符串中的每个单词添加了单引号。如果我改为引用“$ myArg”,那么对于整个字符串而不是每个单词都会出现相同的情况。
现在,假设代替echo
,我们将字符串传递给一个程序,其中一些参数需要引用模式,例如"*"
(不能通过壳)。
为了澄清,我不希望在扩展期间添加单引号。我怎么能实现这个目标?
答案 0 :(得分:16)
不要使用引号,使用数组(请参阅BashFAQ #050):
$ myArgs=("hello" "world" "multiword arg with * ?")
+ myArgs=("hello" "world" "multiword arg with * ?")
$ echo "${myArgs[@]}"
+ echo hello world 'multiword arg with * ?'
hello world multiword arg with * ?
如果它确实需要以字符串中的引用字符串形式存在,那么您将不得不使用类似eval "echo $myArg"
的内容(如果您不是&#,可能会导致一些非常讨厌的错误) 39;小心)或自己解析(这将是困难的)。
答案 1 :(得分:6)
如果您想将变量值作为参数传递(99%的案例在SO上),只需使用正确的quoting:
arg="foo bar"
command "$arg"
如果要传递多个参数,请使用数组:
args=("foo bar" "baz ban" bay)
command "${args[@]}"
答案 2 :(得分:0)
我不认为它正在做你认为它正在做的事情。
[~]$ myArg="\"hello\" \"world\""
[~]$ echo "string is:" $myArg
string is: "hello" "world"
我看不到任何类型的额外引号 - echo
获得三个参数字符串。
[~]$ cargs(){ echo $#; }
[~]$ cargs "string is:" $myArg
3
Bash会先扩展变量,所以
cargs "string is:" $myArg
成为(虽然没有文字反斜杠 - 这就是字符串转义是PITA的原因)
cargs "string is:" "\"hello\"" "\"world\""
args数组是:
0x00:string is:0
0x0B:"hello"0
0x13:"world"0
0x1B:0
现在,如果你在其中一个中添加*
或glob路径扩展,Bash将在此时展开它,除非你将其转义,或者在文字命令中使用单引号。
[~]$ cargs "string is:" $myArg *
19
[~]$ cargs "string is:" $myArg "\*"
4
[~]$ cargs "string is:" $myArg '*'
4
答案 3 :(得分:0)
有一种可移植的方法来拆分扩展变量但保留空格。不需要Bash数组。 Dash(Ubuntu的/ bin / sh)也可以。
使用一些字符来分隔参数中绝对不使用的参数。下面的示例使用分号,但它可以是换行符或其他字符。扩展参数列表时,暂时将IFS
变量更改为换行符。尽快将IFS
恢复为原始值,即使这意味着在循环中执行此操作。如果不保证循环至少运行一次,也可以在循环之后执行。
#! /bin/sh
arg_list='hello world;have a nice day'
save_IFS="$IFS"
IFS=';'
for i in $arg_list; do
IFS="$save_IFS"
echo "$i"
done
IFS="$save_IFS"
请注意,每个展开的参数都是单独打印的。
$ ./test.sh
hello world
have a nice day