如何将带引号的多字字符串替换为参数?
Posted
技术标签:
【中文标题】如何将带引号的多字字符串替换为参数?【英文标题】:How to substitute quoted, multi-word strings as arguments? 【发布时间】:2012-03-18 01:37:44 【问题描述】:我正在尝试将包含多个引号的字符串变量替换为命令的参数。
因此,给定以下示例脚本(注意 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
,其中一些参数需要被引用模式,例如"*"
(不能被shell扩展)。
为了澄清,我不希望在扩展过程中添加单引号。我怎样才能做到这一点?
【问题讨论】:
你在做什么?除非你对eval
做一些讨厌的事情,否则传递给程序的字符串是否包含"*"
或*
应该无关紧要。
致任何困惑的人:注意 shebang 中的 -x
,它会导致输出被记录。
@Pumbaa80,确实,我已在问题中添加了该说明。
与:***.com/questions/17338863/…一起有用
【参考方案1】:
如果您想将变量值作为参数传递(SO 上 99% 的情况),只需使用正确的quoting:
arg="foo bar"
command "$arg"
如果要传递多个参数,请使用数组:
args=("foo bar" "baz ban" bay)
command "$args[@]"
【讨论】:
正如@gordon-davisson 所澄清的那样,数组确实是答案,非常感谢!【参考方案2】:不要使用引号,使用数组(参见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"
之类的东西(如果你不小心,这可能会导致一些非常讨厌的错误)或自己解析(这会很困难)。
【讨论】:
这种数组方法非常有效,非常感谢!附言。来自子 shell 的任何打印操作都由父 shell 解释,因此任何这样的“eval”语句似乎都给出了同样的坏结果。【参考方案3】:我不认为它正在做你认为它正在做的事情。
[~]$ 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
【讨论】:
Echo 的 output 确实完美地打印了引用的单词,但是传递给 echo 的输入参数(如问题中调试输出的第二行所示)是单引号 -双引号('"str"'),不幸的是,这对于我正在使用的工具来说是毫无意义的输入。【参考方案4】:有一种可移植的方式来拆分扩展变量但保留空格。不需要 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
【讨论】:
以上是关于如何将带引号的多字字符串替换为参数?的主要内容,如果未能解决你的问题,请参考以下文章