假设有双引号,单引号和&没有报价

时间:2016-04-27 09:18:32

标签: bash

在bash中:

使用双引号

echo "*" #Globbing is never done
echo "$variable" # Variable expansion is always done
echo "$(command)" # command expansion is always done

使用单引号

echo '*' #Globbing is never done 
echo '$variable' # Variable expansion is never done
echo '$(command)' # command expansion is never done

不使用引号

echo * #Globbing always done.
echo $variable; # Variable expansion is always done
echo $(command) # command expansion is always done

这适用于所有命令吗?

6 个答案:

答案 0 :(得分:4)

看起来你正在寻找异常,我猜你有一些想法。我将假设set -f / set -o noglob被排除在此案例之外?

使用dd命令时,即使没有引用,也不会出现globbing。

$ ls *.txt
blah.txt  file1.txt  file2.txt  file.txt  logfile.txt
$ dd if=*.txt of=glob.txt
dd: failed to open ‘*.txt’: No such file or directory

反驳和误报

以下是一些奇数的示例,但请遵循扩展

variable='2010-09-08 12:34:56' echo "$variable" | xargs date +%s -d date: extra operand '12:34:56'

额外的操作数显示变量扩展正在发生,您正在丢失管道中的引号。 $ date +%s -d 2010-09-08 12:34:56 date: extra operand ‘12:34:56’

如果您为echo $1创建脚本,然后在传递时展开您的引用变量,也会发生这种情况。它扩展,并按预期工作。所以,问题不在于xargs,而在管道之前的扩展是正常的。

  1. Eval ... evals的全部目的是在运行命令之前扩展其args。扩展也发生在bash -c,除了它需要一个参数。因此,这不是扩展问题,而是命令使用问题。
  2. cmd='printf "%s\n" "$(date -d "$variable" +%c)"' bash -c $cmd

    与扩展版

    的作用相同

    $ bash -c printf "%s\n" "$(date -d "$variable" +%c)" printf: usage: printf [-v var] format [arguments]

    1. 我非常喜欢Hauri的$'...'和$“......”信息 - 然而,这些与我们所说的不一样。实际上它们就像bash手册页所说的那样。 $''与''不同,因为(())来自$(())

    2. 我对这个感到很兴奋,所以...... $ ls mclark.txt qt sign_in.txt skel.bash $ zip m*t.zip *t $ ls *.zip m*t.zip

    3. 然而,这也不正确 - splat扩展,但没有匹配时zip将其用作文字。我找到了一些执行此操作的命令,但如果有匹配(我之后添加了my.zip),则使用匹配的扩展(抛出错误,b / c my.zip是用于测试目的的文本文件)。

答案 1 :(得分:3)

有多种力量到位。通常,您可以假设单引号是隐藏bash扩展中的内容。双引号是对可能具有空格的值进行分组,以便bash将它们视为一个逻辑单元,但也禁用globbing。虽然有很多警告......

  

用双引号括起字符可保留字面值   引号中的所有字符,$,',\和的例外情况除外   启用历史记录扩展时,!字符$和'保留   它们在双引号内的特殊含义。反斜杠保留   只有在以下其中一项之后才有其特殊含义   字符:$,',",\或。可以引用双引号   在双引号内用前面的反斜杠。如果启用,   除非一个人进行历史扩张!双重出现   引号使用反斜杠进行转义。反斜杠预先发布!   没有删除。

请参阅man bash

中的QUOTING部分

下面的这个示例将使您进一步混淆或更清楚。

$ echo "*test*"
*test*

$ echo '*test*'
*test*

$ msg=$(echo '*test*')
$ echo '$msg'
$msg

$ echo "$msg"
*test*

$ echo $msg
speedtest test1 test2 test3 test4 test5 testdir

请注意,如果没有匹配,则会打印*test*而非空行,如Hastur所评论。

其他一些有趣的花絮

请注意,这不起作用

$ echo 'single quotes don\'t escape'

但这有效

$ echo "\"double quotes\" escape"

但你可以在不使用其他内容的情况下使用其中一个

$ echo '"' "'"

答案 2 :(得分:2)

如果没有匹配* .xtx,而a.txt是文件    mv a.txt * .xtx 也会给你带来意想不到的结果。 这同样适用于其他类似cp的东西,甚至将其视为引用:

$ ls *.xtx
/bin/ls: cannot access *.xtx: No such file or directory
$ echo "A" > *.xtx
$ ls *.xtx
*.xtx
$

虽然他们都应该返回错误,就像你会得到更多的文件一样"模糊的重定向"。

答案 3 :(得分:2)

简答:是

这个假设 basicaly 是真的,总是这样!

variable='2010-09-08 12:34:56' 
vname=variable
date -d "$variable" +%s
1283942096

date -d "${!vname}" +%s
1283942096

date -d $variable +%s
date: extra operand '+%s'
Try 'date --help' for more information.

date -d '$variable' +%s
date: invalid date '$variable'

date -d ${!vname} +%s
date: extra operand '+%s'
Try 'date --help' for more information.

但是

  1. xargs等命令正好与扩展和参数分配有关。

    echo "$variable" | xargs date +%s -d
    date: extra operand '12:34:56'
    Try 'date --help' for more information.
    

    您必须使用-0 arg到xargs

    echo "$variable" | xargs -0 date +%s -d
    1283942096
    
  2. 内置命令可以使用不同的方式,特别是eval

    cmd='printf "%s\n" $(date -d "$variable" +%c)'
    eval $cmd
    Wed
    Sep
    8
    12:34:56
    2010
    
    cmd='printf "%s\n" "$(date -d "$variable" +%c)"'
    eval "$cmd"
    Wed Sep  8 12:34:56 2010
    
    eval $cmd
    Wed Sep  8 12:34:56 2010
    
    bash -c "$cmd"
    Mon May 16 00:00:00 2016
    
    bash -c $cmd
    printf: usage: printf [-v var] format [arguments]
    
  3. bash下有趣的东西的语法不仅限于".."'..'${}

    • $'...'允许您打印特殊字符,但不要扩展变量:

      echo $'This\tis\ta string containing ${variable}'
      This    is  a string containing ${variable}
      
    • 反引号:为了兼容性,始终支持反引号。如果不是非常易读,您可能会在某些脚本中看到这一点:

      echo `date +%c -d "${!vname}"`
      Wed Sep 8 12:34:56 2010
      
    • 语法$"..."可用于本地化:

      export TEXTDOMAIN=bash
      export LANG=fr_CH.utf-8
      echo $"Running"
      En cours d'exécution
      

答案 4 :(得分:1)

  

这适用于所有命令吗?

来自Bash参考手册:

3.1.2.2 Single Quotes

  

用单引号(')括起字符可保留文字   引号内每个字符的值。单引号可能不会   发生在单引号之间,即使前面有反斜杠。

3.1.2.3 Double Quotes

  

用双引号(")括起字符可以保留文字   引号内所有字符的值,$除外,   `,\,和,当启用历史记录扩展时,!那些角色   $和`在双引号中保留它们的特殊含义(见   Shell Expansions)。反斜杠只保留其特殊含义   当后跟一个以下字符时:$,`,",\,   或换行符。在双引号内,后跟一个反斜杠   这些字符被删除。字符前面的反斜杠   没有特殊含义的是未经修改的。双引号可能是   在双引号内引用,前面加一个反斜杠。如果   启用后,将执行历史记录扩展,除非!出现   在双引号中使用反斜杠进行转义。前面的反斜杠   的!没有删除。

     

特殊参数*和@在double时具有特殊含义   引号(见Shell Parameter Expansion)。

答案 5 :(得分:1)

shell参考手册和shell手册页可能包含预期的行为......但结果可能并不总是最初的预期。

阅读" QUOTING"手册页的部分也很有意思。这是bash手册页中有关单引号和双引号的部分:(与参考手册的内容几乎相同)

  

用单引号括起字符可保留字面值   引号中的每个字符。单引号可能不会发生   单引号之间,即使前面有反斜杠。

     

用双引号括起字符可保留字面值   引号中的所有字符,$,`,\和的除外,   启用历史记录扩展时,!字符$和`   在双引号中保留其特殊含义。反斜杠   只有在遵循下列之一时才保留其特殊含义   字符:$,`,",\或。双引号可能是   在双引号内引用,前面加一个反斜杠。如果   启用后,将执行历史记录扩展,除非!   出现在双引号中使用反斜杠进行转义。该   之前的反斜杠!没有删除。