使用以下简化代码提取:
DIR='a b'
mount_command="./mount.cpfs $loop $DIR -f $OPTS"
sudo $mount_command
启用跟踪时执行此行:
+ sudo ./mount.cpfs /dev/loop0 a b -f -o default_permissions,allow_other,attr_timeout=0
但DIR
未被引用,因此a
和b
作为不同参数传递,而不是./mount.cpfs
传递。
创建这样的命令序列,然后将其扩展到更高版本的命令行的最佳方法是什么?
请记住,代码示例已简化为核心问题,我在几个地方使用mount_command
并在其之前和之后添加了各种内容,并且DIR
由用户传入。在分配给DIR
时,我尝试了几种引用mount_command
的组合,以及使用数组的原始尝试。
mount_command
mount_command="./mount.cpfs $loop $DIR -f $OPTS"
case "$MODE" in
gdb)
sudo gdb -return-child-result -x gdbbatch \
--args $mount_command
;;
normal)
sudo $mount_command
;;
valgrind)
sudo valgrind --track-fds=yes --leak-check=full --malloc-fill=0x80 \
--free-fill=0xff $mount_command
;;
*)
echo "Mode '$MODE' unknown"
mounted=''
exit 2
;;
esac
请测试您的建议,我认为解决方案并不简单。
答案 0 :(得分:5)
bash中最好的方法是使用数组。数组将保持单独的单词,这些单词是分开的,并在单个单词中保留空格:
DIR='a b'
mount_command=(./mount.cpfs $loop "$DIR" -f $OPTS)
sudo "${mount_command[@]}"
展开"${mount_command[@]}"
时,每个元素都会作为单个参数展开到sudo
,即使它有空格。
请注意我引用"$DIR"
但不引用$OPTS
的方式,因为您的$OPTS
包含多个要作为单独的单词传递给mount命令的单词,但应保留$DIR
一起。但是,您可以使用与mount_command
相同的方式使OPTS成为数组,并在mount_command
定义中将其展开为"${OPTS[@]}"
:
DIR='a b'
OPTS=(-o default_permissions,allow_other,attr_timeout=0)
mount_command=(./mount.cpfs $loop "$DIR" -f "${OPTS[@]}")
sudo "${mount_command[@])"
在bash脚本中完成了大量的命令构建之后,我发现数组远远优于试图找出正确的引用(如果可能的话)来将命令保存在一个简单的字符串中。
答案 1 :(得分:1)
尝试使用 eval 。
给出以下脚本,名为 test :
#!/bin/bash
# test
echo $1
如果我这样做:
DIR='a b'
CMD=."/test \"$DIR\""
eval $CMD
输出
a b
答案 2 :(得分:0)
DIR='a b'
OPTS='-o allow_other,attr_timeout=0'
mount_command="./mount.cpfs '$loop' '$DIR' -f '$OPTS'"
eval sudo $mount_command
这应该有效。很难理解shell中的引用,因为它很多 与其他语言不同。
在你的情况下,你需要引用'$ DIR'变量(并且更好的是所有可以包含空格的变量)。这很清楚。 但shell只解释一次字符串!你需要指导它 使用命令 eval 重新解释。如果没有 eval ,则变量$ mount_command为 扩展但内部引用未处理。
你可以阅读我的短文: White Shell
答案 3 :(得分:-1)
尝试
mount_command="./mount.cpfs $loop \"$DIR\" -f $OPTS"
试试这个:
DIR='a b'
#following line replaces space occurrences with "\ "
DIR=`echo $DIR | replace ' ' '\ '`
mount_command="./mount.cpfs $loop $DIR -f $OPTS"
sudo $mount_command