如何防止双引号被单引号括起来

时间:2017-04-10 19:03:11

标签: bash shell

我确信之前已经问过,但我老实说不知道该搜索什么。所以请考虑这个小小的脚本:

#!/bin/sh
test="\"Hello\" \"World\""
set -x
echo $test

结果将是:

+ echo '"Hello"' '"World"'
"Hello" "World"

但那不是我想要的!我不希望在echo个参数周围有单引号。我想要的是这个:

+ echo "Hello" "World"
Hello World

我怎样才能实现这一目标?

*编辑*

以下是上图中背后真正问题的一个更具体的例子:

#!/bin/sh

alldirs=

for d in */ ; do
    dir=${d%?}
    alldirs+=" \"$dir\""
done

set -x
tar cvf test.tar.gz $alldirs

我们的想法是将脚本目录中的所有目录存档在tar存档中。由于目录名称可能包含空格,因此我将它们的名称括在双引号中。

上面的脚本不起作用。 tar抱怨由于双引号而无法在各个目录上运行stat

2 个答案:

答案 0 :(得分:6)

我窥探了你的历史,发现你熟悉类C语言:

int main() {
  char *s = "\"hello\", \"world\"";
  printf("First: %s, second: %s\n", s);
}

您希望这相当于

printf("First: %s, second: %s\n", "hello", "world);

相反,它写道:

first: "hello", "world", second: 

那么为什么printf会添加额外的引号?答案很明显,事实并非如此。解释引号不是printf的工作。文字引号不会影响C函数接收字符串的方式。

同样,解释引号不是echotar的工作。文字引号不会影响shell命令接收字符串的方式。

C和bash中的解决方案是将值放在数组中,而不是尝试创建一个带有嵌入引号的字符串:

#!/bin/bash
alldirs=()

for d in */ ; do
    dir=${d%?}
    alldirs+=("$dir")
done

set -x
tar cvf test.tar.gz "${alldirs[@]}"

这当然只是为了说明。真实的脚本会将此简化为tar cvf test.tar.gz */

答案 1 :(得分:0)

我不确定这是否适用于您的确切脚本,但您不需要使用双引号。

你可以试试这个:

#!/bin/sh
test=Hello\ World
set -x
echo $test