請勿繞過參數引號 - 當您這樣做時,引號將被視爲參數的一部分,例如在文件名中查找帶有實際引號的文件。使用這樣的事情:
f() {
searchpath=$1
filepat=$2
greppattern=$3
find "$searchpath" -name "$filepat.[ch]" -exec grep --color -aHn "$greppattern" {} \;
}
[編輯]擴大我的意見對報價被視爲參數的一部分:在一個命令行報價如何影響它們內部的文本進行解析。雙引號允許變量引用('$ varname`)被擴展和一些其他的東西,但沒有其他的東西。一旦它們產生了這種效果,它們就會被移除(即它們不會傳遞給命令本身)。看到這一點,讓我們來定義,只是打印其參數的函數,看看它實際上是從各種命令行接收:
$ printargs() { printf " <%s>\n" "[email protected]"; }
$ printargs one two
<one>
<two>
$ printargs "one" "two" # The quotes will be removed before printargs sees them
<one>
<two>
$ printargs "one two" # The quotes make the two words into one argument, but again aren't passed on to printargs
<one two>
$ printargs "one" 'two' three # Single-quotes are also removed
<one>
<two>
<three>
類似的事情發生與變量:
$ var="one two" # Note that the quotes are removed before the value is stored in $var
$ printargs $var # Variable is substituted, then its value is parsed into separate words
<one>
<two>
$ printargs "$var" # Double-quotes here allow the variable to be expanded, but prevent further parsing
<one two>
$ printargs '$var' # Single-quotes prevent even variable expansion
<$var>
如果你逃跑的報價但是,他們沒有任何這些影響;他們只是作爲參數的一部分:
$ printargs \"one\" \'two\' \"three four\"
<"one">
<'two'>
<"three>
<four">
$ printargs \"$var\"
<"one>
<two">
......這幾乎從來沒有你想要的。特別是,隨着find
命令:
$ searchpath=.
$ filepat='*'
$ greppattern='#ifdef'
$ printargs "$searchpath" -name "$filepat.[ch]" -exec grep --color -aHn "$greppattern" {} \;
<.>
<-name>
<*.[ch]>
<-exec>
<grep>
<--color>
<-aHn>
<#ifdef>
<{}>
<;>
$ printargs "$searchpath" -name \"$filepat.[ch]\" -exec grep --color -aHn \"$greppattern\" {} \;
<.>
<-name>
<"*.[ch]">
<-exec>
<grep>
<--color>
<-aHn>
<"#ifdef">
<{}>
<;>
...在第二個(包含轉義引號)的報價傳遞給find
,並把它們作爲文件名模式的一部分,尋找與雙文件名字中的引號。如果它找到了任何東西,那麼grep
命令會發生同樣的事情 - 它會尋找#ifdef的周圍有雙引號。
非常感謝你的工作!還有一個問題:當你說「引號被視爲論證的一部分」時,我不明白你的意思。你是指發現的論點?如果是這樣,爲什麼我直接在shell中需要引號?再次感謝! – Plouff
@Plouff:查看編輯 –
哇!非常感謝你的詳細解答!我意識到「」和「'之間關於變量擴展的區別,但我從來沒有聽說過這個背後的真正機制。 'var =「one two」'的部分讓我大開眼界。再次感謝你! – Plouff