如何用引号,多字符串作为参数替换?

时间:2012-02-28 15:05:39

标签: bash shell command-line-arguments quotes

我正在尝试将包含多个引用词的字符串变量替换为命令的参数。

因此,给出以下示例脚本(注意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,我们将字符串传递给一个程序,其中一些参数需要引用模式,例如"*"(不能通过壳)。

为了澄清,我不希望在扩展期间添加单引号。我怎么能实现这个目标?

4 个答案:

答案 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