[英]Assumption with double quotes, single quotes & no quotes
在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
這適用於所有命令嗎?
看起來你正在尋找異常,我猜你有一些想法。 我將假設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是用於測試目的的文本文件)。
有多種力量到位。 通常,您可以假設單引號是隱藏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 '"' "'"
如果沒有任何內容匹配* .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
$
雖然他們都應該返回錯誤,就像有一個文件更多,你會得到“模糊的重定向”。
總的來說 ,這種假設基本上是正確的!
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
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]
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
這適用於所有命令嗎?
是。
來自Bash參考手冊:
用單引號(
'
)括起字符可以保留引號中每個字符的字面值。 單引號之間可能不會出現單引號,即使前面有反斜杠也是如此。
和
用雙引號括起來的字符(
"
)保留引號內所有字符的字面值,但$,`,\\除外,並且,當啟用歷史擴展時,!。字符$和`在double中保留它們的特殊含義引號(參見Shell Expansions )。反斜杠只有在跟隨以下字符之一時才保留其特殊含義:$,`,“,\\或newline。 在雙引號內,將刪除后跟其中一個字符的反斜杠。 沒有特殊含義的字符前面的反斜杠不做修改。 雙引號可以在雙引號內引用,前面加一個反斜杠。 如果啟用,將執行歷史記錄擴展,除非! 出現在雙引號中使用反斜杠進行轉義。 之前的反斜杠! 沒有刪除。在雙引號中,特殊參數*和@具有特殊含義(參見Shell參數擴展 )。
shell參考手冊和shell手冊頁可能包含預期的行為......但結果可能並不總是最初的預期。
閱讀手冊頁的“QUOTING”部分也很有意思。 這是bash手冊頁中有關單引號和雙引號的部分:(與參考手冊的內容幾乎相同)
用單引號括起字符可以保留引號中每個字符的字面值。 單引號之間可能不會出現單引號,即使前面有反斜杠也是如此。
用雙引號括起字符會保留引號內所有字符的字面值,但$,`,\\除外,並且,當啟用歷史記錄擴展時,! 字符$和`在雙引號中保留其特殊含義。 反斜杠只有在跟隨以下字符之一時才會保留其特殊含義:$,`,“,\\或者。雙引號可以在雙引號之前用反斜杠引用。如果啟用,則歷史記錄將擴展除非使用反斜杠轉義出現在雙引號中的!,否則不會刪除!之前的反斜杠。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.