问题描述
这是我的问题.在 bash 3 中:
This is my problem. In bash 3:
$ test='One "This is two" Three'
$ set -- $test
$ echo $2
"This
如何让 bash 理解引号并将 $2 返回为 This is two
而不是 "This
?不幸的是,我无法更改名为 的变量的构造在这个例子中测试
.
How to get bash to understand the quotes and return $2 as This is two
and not "This
? Unfortunately I cannot alter the construction of the variable called test
in this example.
推荐答案
发生这种情况的原因是 shell 解析命令行的顺序:它解析(并删除)引号和转义符,然后替换变量值.当 $test
被 One "This is two" Three
取代时,引号要达到预期效果为时已晚.
The reason this happens is because of the order in which the shell parses the command line: it parses (and removes) quotes and escapes, then replaces variable values. By the time $test
gets replaced with One "This is two" Three
, it's too late for the quotes to have their intended effect.
简单(但危险)的方法是使用 eval
添加另一个级别的解析:
The simple (but dangerous) way to do this is by adding another level of parsing with eval
:
$ test='One "This is two" Three'
$ eval "set -- $test"
$ echo "$2"
This is two
(请注意,echo
命令中的引号不是必需的,但这是一个很好的通用做法.)
(Note that the quotes in the echo
command are not necessary, but are a good general practice.)
我说这很危险的原因是它不仅返回并重新解析带引号的字符串,它还返回并重新解析所有内容,可能包括您不想像命令一样解释的内容替代品.假设你已经设置了
The reason I say this is dangerous is that it doesn't just go back and reparse for quoted strings, it goes back and reparses everything, maybe including things you didn't want interpreted like command substitutions. Suppose you had set
$ test='One `rm /some/important/file` Three'
...eval
实际上会运行 rm
命令.所以如果你不能指望 $test
的内容是安全的",不要使用这个结构.
...eval
will actually run the rm
command. So if you can't count on the contents of $test
to be "safe", do not use this construct.
顺便说一句,做这种事情的正确方法是使用数组:
BTW, the right way to do this sort of thing is with an array:
$ test=(One "This is two" Three)
$ set -- "${test[@]}"
$ echo "$2"
This is two
不幸的是,这需要控制变量的创建方式.
Unfortunately, this requires control of how the variable is created.
这篇关于将字符串转换为参数时,Bash 不解析引号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!