Bash 双引号、单引号和;无报价

Bash 双引号、单引号和;无报价,bash,Bash,在bash中: 使用双引号 echo“*”#全球化永远不会完成 echo“$variable”#始终完成变量扩展 echo“$(命令)”#命令扩展始终完成 使用单引号 echo'*.\Globbing从未完成 echo“$variable”#变量扩展从未完成 echo“$(命令)#命令扩展从未完成 不使用引号 echo*#始终完成全球化。 echo$variable;#变量展开总是完成的 echo$(命令)#命令扩展始终完成 这是否适用于所有命令?存在多个力。通常,您可以假设单引号是为了

在bash中:

使用双引号
echo“*”#全球化永远不会完成
echo“$variable”#始终完成变量扩展
echo“$(命令)”#命令扩展始终完成
使用单引号
echo'*.\Globbing从未完成
echo“$variable”#变量扩展从未完成
echo“$(命令)#命令扩展从未完成
不使用引号
echo*#始终完成全球化。
echo$variable;#变量展开总是完成的
echo$(命令)#命令扩展始终完成

这是否适用于所有命令?

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

将字符括在双引号中可保留 引号中的所有字符,除了$,',\,和, 启用历史扩展时!。字符$和“retain” 它们在双引号中的特殊含义。反斜杠保持不变 它的特殊含义只有在后面跟着下列之一时才有 字符:$,',“,\,或。可以引用双引号 在双引号内,在其前面加上反斜杠。如果启用, 除非!以双精度显示,否则将执行历史扩展 引号是使用反斜杠转义的。反斜杠预先放弃引号! 没有删除

请参阅引用《man bash》中的章节

下面的这个例子要么会让你更加困惑,要么会让你更清楚

$ 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 '"' "'"
这是否适用于所有命令

来自Bash参考手册:

将字符括在单引号(
)中会保留文字 引号内每个字符的值。单个引号不能 出现在单引号之间,即使前面有反斜杠

在双引号(
)中包含字符将保留文字 引号内所有字符的值,美元除外, `,\,并且,当启用历史扩展时!。人物 $和`在双引号中保留其特殊含义(参见 ).反斜杠仅保留其特殊含义 后跟以下字符之一时:$,`,“,\, 或换行符。在双引号中,后跟一个的反斜杠 已删除其中的个字符。前一个字符的反斜杠 如果没有特殊含义,则不作修改。可以使用双引号 在双引号中加反斜杠引起来。如果 已启用,除非出现!否则将执行历史扩展 在双引号中,使用反斜杠进行转义 未删除该文件

特殊参数*和@在双精度模式下具有特殊含义 引用(见)


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

阅读手册中的“引用”部分也很有趣。这是bash手册中关于单引号和双引号的部分:(与参考手册的内容几乎相同)

将字符括在单引号中可以保留 引号中的每个字符。可能不会出现单个引号 在单引号之间,即使前面有反斜杠

将字符括在双引号中可保留 引号中的所有字符,美元、`、\、和除外, 启用历史扩展时,!。字符$和` 在双引号中保留其特殊含义。反斜杠 仅当后跟以下其中一项时,才保留其特殊含义 字符:$、`、\、或。双引号可以是 在双引号中加反斜杠引起来。如果 启用后,将执行历史记录扩展,除非! 出现在双引号中时使用反斜杠进行转义。这个 在前面加反斜杠!没有删除


看起来你在寻找例外情况,我想你一定有一些想法。我将假设
set-f
/
set-o noglob
被排除在本例之外

使用
dd
命令时,即使未加引号,也不会发生全局绑定

$ 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'
回显“$variable”| xargs日期+%s-d
日期:额外操作数“12:34:56”

额外的操作数表示正在进行变量扩展,您正在丢失管道中的引号。
$date+%s-d2010-09-0812:34:56
日期:额外操作数“12:34:56”

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

  • 评估。。。evals的全部目的是在运行命令之前对其参数进行扩展。除了需要一个参数外,
    bash-c
    也会进行扩展。因此,这不是一个扩展问题,而是一个命令使用问题
  • cmd='printf”%s\n”“$(日期-d“$变量”+%c)'
    bash-c$cmd

    工作原理与扩展版本相同

    $bash-c printf“%s\n”$(日期-d“$variable”+%c)
    printf:usage:printf[-v var]格式[参数]
    

    $ ls *.xtx
    /bin/ls: cannot access *.xtx: No such file or directory
    $ echo "A" > *.xtx
    $ ls *.xtx
    *.xtx
    $
    
    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.
    
    echo "$variable" | xargs date +%s -d
    date: extra operand '12:34:56'
    Try 'date --help' for more information.
    
    echo "$variable" | xargs -0 date +%s -d
    1283942096
    
    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]
    
    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