在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
这适用于所有命令吗?
答案 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,而在管道之前的扩展是正常的。
bash -c
,除了它需要一个参数。因此,这不是扩展问题,而是命令使用问题。 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]
我非常喜欢Hauri的$'...'和$“......”信息 - 然而,这些与我们所说的不一样。实际上它们就像bash手册页所说的那样。 $''与''不同,因为(())来自$(())
我对这个感到很兴奋,所以......
$ ls
mclark.txt qt sign_in.txt skel.bash
$ zip m*t.zip *t
$ ls *.zip
m*t.zip
然而,这也不正确 - splat扩展,但没有匹配时zip将其用作文字。我找到了一些执行此操作的命令,但如果有匹配(我之后添加了my.zip),则使用匹配的扩展(抛出错误,b / c my.zip是用于测试目的的文本文件)。
答案 1 :(得分:3)
有多种力量到位。通常,您可以假设单引号是隐藏bash扩展中的内容。双引号是对可能具有空格的值进行分组,以便bash将它们视为一个逻辑单元,但也禁用globbing。虽然有很多警告......
用双引号括起字符可保留字面值 引号中的所有字符,$,',\和的例外情况除外 启用历史记录扩展时,!字符$和'保留 它们在双引号内的特殊含义。反斜杠保留 只有在以下其中一项之后才有其特殊含义 字符:$,',",\或。可以引用双引号 在双引号内用前面的反斜杠。如果启用, 除非一个人进行历史扩张!双重出现 引号使用反斜杠进行转义。反斜杠预先发布! 没有删除。
请参阅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 '"' "'"
答案 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.
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
内置命令可以使用不同的方式,特别是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]
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参考手册:
用单引号(
'
)括起字符可保留文字 引号内每个字符的值。单引号可能不会 发生在单引号之间,即使前面有反斜杠。
和
用双引号(
"
)括起字符可以保留文字 引号内所有字符的值,$除外, `,\,和,当启用历史记录扩展时,!那些角色 $和`在双引号中保留它们的特殊含义(见 Shell Expansions)。反斜杠只保留其特殊含义 当后跟一个以下字符时:$,`,",\, 或换行符。在双引号内,后跟一个反斜杠 这些字符被删除。字符前面的反斜杠 没有特殊含义的是未经修改的。双引号可能是 在双引号内引用,前面加一个反斜杠。如果 启用后,将执行历史记录扩展,除非!出现 在双引号中使用反斜杠进行转义。前面的反斜杠 的!没有删除。特殊参数*和@在double时具有特殊含义 引号(见Shell Parameter Expansion)。
答案 5 :(得分:1)
shell参考手册和shell手册页可能包含预期的行为......但结果可能并不总是最初的预期。
阅读" QUOTING"手册页的部分也很有意思。这是bash手册页中有关单引号和双引号的部分:(与参考手册的内容几乎相同)
用单引号括起字符可保留字面值 引号中的每个字符。单引号可能不会发生 单引号之间,即使前面有反斜杠。
用双引号括起字符可保留字面值 引号中的所有字符,$,`,\和的除外, 启用历史记录扩展时,!字符$和` 在双引号中保留其特殊含义。反斜杠 只有在遵循下列之一时才保留其特殊含义 字符:$,`,",\或。双引号可能是 在双引号内引用,前面加一个反斜杠。如果 启用后,将执行历史记录扩展,除非! 出现在双引号中使用反斜杠进行转义。该 之前的反斜杠!没有删除。