引用bash变量赋值

时间:2010-09-08 07:35:47

标签: linux bash shell ubuntu

使用以下简化代码提取:

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未被引用,因此ab作为不同参数传递,而不是./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

Update0

请测试您的建议,我认为解决方案并不简单。

4 个答案:

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

请参阅this question

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