如何在shell脚本中保留$ @中的双引号?

问题描述:

比方说,我有一个非常简单的shell脚本 '富':

#!/bin/sh 
    echo [email protected] 

如果我调用它像这样:

foo 1 2 3 

它高兴地打印:

1 2 3 

然而,让我们说我的一个论点是双引号括起来并包含空格:

foo 1 "this arg has whitespace" 3 

富高兴地打印:

1 this arg has whitespace 3 

双引号被剥夺!我知道贝壳认为它帮了我一个忙,但是......我希望得到原始版本的论证,不受壳层解释的影响。有没有办法做到这一点?

您需要引用报价:

foo 1 "\"this arg has whitespace\"" 3 

或(更简单)

foo 1 '"this arg has whitespace"' 3 

你需要引用的双引号,以确保在解析时shell不删除它们单词参数。

首先,您可能需要引用版本[email protected],即"[email protected]"。为了感受不同,尝试在字符串中放置多个空格。

其次,引号是shell的语法元素 - 它不会帮你一个忙。为了保护它们,你需要逃避它们。例子:

foo 1 "\"this arg has whitespace\"" 3 

foo 1 '"this arg has whitespace"' 3 

双引号$ @:

#!/bin/sh 
for ARG in "[email protected]" 
do 
    echo $ARG 
done 

然后:

foo 1 "this arg has whitespace" 3 

会给你:

1 
this arg has whitespace 
3 
+0

然后我们可以使用'IFS'来避免在其他答案中引用地狱,如果有人想用这些参数做任何有用的事情.... – 2017-08-02 00:01:16

让我们假设你是在一个更严格的一套并且你不能改变你的命令行,然后make它通过逃避双引号更“友好”。例如:

example_script.sh argument_without_quotes "argument with quotes i cannot escape" 

首先考虑的是你的脚本中如果参数是带或不带引号过去了,你看不出来,因为外壳剥离它们。

所以你能做的重建双引号包含空格

这个例子重建整个命令行,有空格

#!/bin/sh 
#initialize the variable that will contain the whole argument string 
argList="" 
#iterate on each argument 
for arg in "[email protected]" 
do 
    #if an argument contains a white space, enclose it in double quotes and append to the list 
    #otherwise simply append the argument to the list 
    if echo $arg | grep -q " "; then 
    argList="$argList \"$arg\"" 
    else 
    argList="$argList $arg" 
    fi 
done 

#remove a possible trailing space at the beginning of the list 
argList=$(echo $argList | sed 's/^ *//') 

#pass your argument list WITH QUOTES 
echo "my_executable" $argList 
#my_executable $argList 

注意这一限制双引号的论点论据。如果你运行这个例子

你会得到这个输出

my_executable "argument with spaces" argument_without_spaces argument_doublequoted_but_without_spaces 

注意最后一个参数:因为它没有空格,它并没有被用双引号括再次,但是这不应该成为一个问题。

我会做的是引用所有收到的空格,可能会帮助你的情况。

for x in "${@}" ; do 
    # try to figure out if quoting was required for the $x 
    if [[ "$x" != "${x%[[:space:]]*}" ]]; then 
     x="\""$x"\"" 
    fi 
    echo $x 
    _args=$_args" "$x 
done 

echo "All Cmd Args are: $_args"