简体   繁体   English

双引号,单引号和无引号的假设

[英]Assumption with double quotes, single quotes & no quotes

In bash : 在bash中:

Using double quotes 使用双引号

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

Using single quotes 使用单引号

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

Using no quotes 不使用引号

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

will this apply for all commands? 这适用于所有命令吗?

It looks like you are looking for exceptions, and I'd guess you have some in mind. 看起来你正在寻找异常,我猜你有一些想法。 I'm going to make the assumption that set -f / set -o noglob are being excluded from this case? 我将假设set -f / set -o noglob被排除在这种情况之外?

When you use the dd command, globbing will not occure, even if unquoted. 当您使用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

Rebuttal and false positives 反驳和误报

Here are some examples that are odd , but follow expansion 以下是一些奇怪的例子,但请遵循扩展

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

The extra operand shows that variable expansion is happening, you are losing the quotes in the pipe. 额外的操作数显示变量扩展正在发生,您正在丢失管道中的引号。 $ date +%s -d 2010-09-08 12:34:56 date: extra operand '12:34:56'

This also happens if you create a script to echo $1 and then expand your quoted variable while passing. 如果您创建一个脚本echo $1 ,然后在传递时展开您的引用变量,也会发生这种情况。 It expands, and works as expected. 它扩展,并按预期工作。 So, the issue is not with xargs, but with your expansion before the pipe which is normal. 所以,问题不在于xargs,而在管道之前的扩展是正常的。

  1. Eval... evals whole purpose is to do expansion of its args prior to running a command. Eval ...... evals的全部目的是在运行命令之前扩展其args。 Expansion also happens with bash -c , except it takes one argument. 扩展也发生在bash -c ,除了它需要一个参数。 So, again, this is not an expansion issue, but a command usage issue. 因此,这不是一个扩展问题,而是一个命令使用问题。

cmd='printf "%s\\n" "$(date -d "$variable" +%c)"' bash -c $cmd

works the same as the expanded version 与扩展版本的工作方式相同

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

  1. I really enjoyed Hauri's $'...' and $"..." information--however, those are not the samething we are talking about. 我真的很喜欢Hauri的$'...'和$“......”信息 - 然而,这些与我们谈论的不一样。 They are in fact behaving as the bash man page says they should. 实际上它们就像bash手册页所说的那样。 $'' is as different from '' as (()) is from $(()) $''与''不同,因为(())来自$(())

  2. I got excited about this one, so... $ ls mclark.txt qt sign_in.txt skel.bash $ zip m*t.zip *t $ ls *.zip m*t.zip 我很兴奋这个,所以... $ ls mclark.txt qt sign_in.txt skel.bash $ zip m*t.zip *t $ ls *.zip m*t.zip

However, this isn't right either-- the splat expands, but upon no match zip uses it as a literal. 然而,这也不对 - splat扩展,但是在没有匹配时zip将其用作文字。 I found a few commands that did this, but if there was a match (I added a my.zip later) it uses the matched expansion (an error was thrown, b/c my.zip was a text file for testing purposes). 我找到了一些执行此操作的命令,但如果有匹配(我之后添加了my.zip),则使用匹配的扩展(抛出错误,b / c my.zip是用于测试目的的文本文件)。

There are multiple forces in place. 有多种力量到位。 In general you can assume that single quotes is to hide the contents from bash expansion. 通常,您可以假设单引号是隐藏bash扩展中的内容。 Double quotes is to group values which might have white space so that bash sees them as one logical unit but also disable globbing. 双引号是对可能具有空格的值进行分组,以便bash将它们视为一个逻辑单元,但也禁用globbing。 There are many caveats though... 虽然有很多警告......

Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, ', \\, and, when history expansion is enabled, !. 用双引号括起字符会保留引号内所有字符的字面值,但$,',\\除外,并且,当启用历史记录扩展时,! The characters $ and ' retain their special meaning within double quotes. 字符$和'在双引号内保留其特殊含义。 The backslash retains its special meaning only when followed by one of the following characters: $, ', ", \\, or . A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expansion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash pre-ceding the ! is not removed. 反斜杠只有在跟随以下字符之一时才保留其特殊含义:$,',“,\\或者。双引号可以在双引号内引用,前面加一个反斜杠。如果启用,将执行历史记录扩展除非出现在双引号中的!使用反斜杠进行转义。不会删除反斜杠!

See section QUOTING from man bash 请参阅man bash QUOTING部分

This example below, will either confuse you further or make it clearer. 下面的这个例子将使您进一步混淆或使其更清晰。

$ echo "*test*"
*test*

$ echo '*test*'
*test*

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

$ echo "$msg"
*test*

$ echo $msg
speedtest test1 test2 test3 test4 test5 testdir

note that if there were no matches it would print *test* not empty line as commented by Hastur. 请注意,如果没有匹配,它将打印*test*而不是空行,如Hastur所评论。

some other interesting tidbits 其他一些有趣的花絮

note that this doesn't work 请注意,这不起作用

$ echo 'single quotes don\'t escape'

but this works 但这很有效

$ echo "\"double quotes\" escape"

but you can use one in other without escaping 但你可以使用其中一个而不逃避

$ echo '"' "'"

If nothing matches *.xtx while a.txt is a file mv a.txt *.xtx will get you an unexpected result too. 如果没有任何内容匹配* .xtx而a.txt是文件mv a.txt * .xtx也会得到意想不到的结果。 The same applies for other things like cp and even this treats it as quoted: 这同样适用于其他类似cp的东西,甚至将其视为引用:

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

While they should all return error just like if there were more the one file you would get "ambiguous redirect". 虽然他们都应该返回错误,就像有一个文件更多,你会得到“模糊的重定向”。

Short answer: Yes 简短回答:是的

This asumptions are basicaly true, alway! 总的来说 ,这种假设基本上是正确的!

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.

But

  1. Some commands like xargs work precisely about expansion and parameter distribution. xargs这样的命令正好适用于扩展和参数分配。

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

    You have to use -0 arg to xargs : 你必须使用-0 arg到xargs

     echo "$variable" | xargs -0 date +%s -d 1283942096 
  2. Builtin commands could use args differently, especialy eval : Builtin命令可以使用不同的args,特别是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. Syntax of funny thing under bash are not limited to ".." , '..' , and ${} bash下有趣的东西的语法不仅限于".."'..'${}

    • $'...' let you print special characters, but don't expand variables: $'...'允许您打印特殊字符,但不扩展变量:

       echo $'This\\tis\\ta string containing ${variable}' This is a string containing ${variable} 
    • Backticks : For compatibility, backtick are always supported. 反引号 :出于兼容性考虑,反引号总是支持。 If not very readable, you may see this in some scripts: 如果不是非常易读,您可能会在某些脚本中看到这一点:

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

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

will this apply for all commands? 这适用于所有命令吗?

Yes. 是。

From Bash reference manuals: 来自Bash参考手册:

3.1.2.2 Single Quotes 3.1.2.2单引号

Enclosing characters in single quotes ( ' ) preserves the literal value of each character within the quotes. 用单引号( ' )括起字符可以保留引号中每个字符的字面值。 A single quote may not occur between single quotes, even when preceded by a backslash. 单引号之间可能不会出现单引号,即使前面有反斜杠也是如此。

and

3.1.2.3 Double Quotes 3.1.2.3双引号

Enclosing characters in double quotes ( " ) preserves the literal value of all characters within the quotes, with the exception of $, `, \\, and, when history expansion is enabled, !. The characters $ and ` retain their special meaning within double quotes (see Shell Expansions ). The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \\, or newline. 用双引号括起来的字符( " )保留引号内所有字符的字面值,但$,`,\\除外,并且,当启用历史扩展时,!。字符$和`在double中保留它们的特殊含义引号(参见Shell Expansions )。反斜杠只有在跟随以下字符之一时才保留其特殊含义:$,`,“,\\或newline。 Within double quotes, backslashes that are followed by one of these characters are removed. 在双引号内,将删除后跟其中一个字符的反斜杠。 Backslashes preceding characters without a special meaning are left unmodified. 没有特殊含义的字符前面的反斜杠不做修改。 A double quote may be quoted within double quotes by preceding it with a backslash. 双引号可以在双引号内引用,前面加一个反斜杠。 If enabled, history expansion will be performed unless an ! 如果启用,将执行历史记录扩展,除非! appearing in double quotes is escaped using a backslash. 出现在双引号中使用反斜杠进行转义。 The backslash preceding the ! 之前的反斜杠! is not removed. 没有删除。

The special parameters * and @ have special meaning when in double quotes (see Shell Parameter Expansion ). 在双引号中,特殊参数*和@具有特殊含义(参见Shell参数扩展 )。

Probably the shell reference manuals and the shell man pages contain the intended behavior ... but the result might not always be what was originally intended. shell参考手册和shell手册页可能包含预期的行为......但结果可能并不总是最初的预期。

Reading the "QUOTING" section of the man pages is also intresting. 阅读手册页的“QUOTING”部分也很有意思。 This is a section from the bash man page concerning the single and double quotes: (which is pretty much the same content as the reference manual) 这是bash手册页中有关单引号和双引号的部分:(与参考手册的内容几乎相同)

Enclosing characters in single quotes preserves the literal value of each character within the quotes. 用单引号括起字符可以保留引号中每个字符的字面值。 A single quote may not occur between single quotes, even when preceded by a backslash. 单引号之间可能不会出现单引号,即使前面有反斜杠也是如此。

Enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \\, and, when history expansion is enabled, !. 用双引号括起字符会保留引号内所有字符的字面值,但$,`,\\除外,并且,当启用历史记录扩展时,! The characters $ and ` retain their special meaning within double quotes. 字符$和`在双引号中保留其特殊含义。 The backslash retains its special meaning only when followed by one of the following characters: $, `, ", \\, or . A double quote may be quoted within double quotes by preceding it with a backslash. If enabled, history expan- sion will be performed unless an ! appearing in double quotes is escaped using a backslash. The backslash preceding the ! is not removed. 反斜杠只有在跟随以下字符之一时才会保留其特殊含义:$,`,“,\\或者。双引号可以在双引号之前用反斜杠引用。如果启用,则历史记录将扩展除非使用反斜杠转义出现在双引号中的!,否则不会删除!之前的反斜杠。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM