2014-10-03 68 views
0

我试图执行以下命令:第二个命令之前猛砸符号化引用字符串用空格作为单个单词

ls: 'my: No such file or directory 
ls: dir': No such file or directory 

使用“设置-x”:

mkdir 'my dir' 
CMD="ls 'my dir'" 
RESULT=$($CMD) 

这导致显示实际发出的命令是:

++ ls ''\''my' 'dir'\''' 

这显然是从我的交流中抽象出来的试着去做;这个代码本身并不起任何作用。但我的问题是为什么bash将引用的字符串标记为这样以及如何让它停止?

+2

查看BashFAQ#50:http://mywiki.wooledge.org/BashFAQ/050 – 2014-10-03 22:03:32

+0

谢谢,这非常有帮助。 – cameronhimself 2014-10-03 22:27:43

+0

另请参阅[BashFAQ#48](http://mywiki.wooledge.org/BashFAQ/048)。正如GreyCat所说,“eval”是一种常见的“邪恶”拼写错误。 :) – 2014-10-04 07:39:34

回答

3

(几乎)所有语言分离代码和数据:

args="1, 2" 
myfunc(args) != myfunc(1, 2) 

相同在bash中是真实的。将单引号放在文字字符串中不会使bash解释它们。

存储程序名和参数(又名一个简单的命令)的正确方法是使用数组:

cmd=(ls 'my dir') 
result=$("${cmd[@]}") 

bash将在空间,除非你双引号,这就是为什么你的榜样有时会自动拆分单词似乎工作。这是令人惊讶和容易出错的,除非你有充分的理由不要,否则你应该总是双引号。

也可以使用eval让bash将字符串解释为完全使用bash代码。这是经常推荐的,但几乎总是错误的。

-1

解决方案1:使用sh -c

mkdir 'my dir' 
CMD="ls 'my dir'" # careful: your example was missing a ' 
RESULT=$(sh -c "$CMD") 

解决方案2:声明CMD作为数组

mkdir 'my dir' 
CMD=(ls 'my dir') # array with 2 elements 
RESULT=$("${CMD[@]}") 
+2

-1:“解决方案1”与使用'eval'完全相同,只是它不允许您在父进程中更改变量,具有执行子进程的所有开销,并将shell从bash切换到在该子命令的持续时间内,本地安装的POSIX sh解释器。 – 2014-10-03 22:02:35