2009-02-09 37 views
4

除了基本的*,?[...]模式之外,Bash shell還提供擴展模式匹配運算符,如!(pattern-list)(「匹配除給定模式之一以外的所有模式」)。需要將extglob shell選項設置爲使用它們。一個例子:如何在引用的表達式中轉義擴展路徑名擴展模式?

~$ mkdir test ; cd test ; touch file1 file2 file3 
~/test$ echo * 
file1 file2 file3 
~/test$ shopt -s extglob # make sure extglob is set 
~/test$ echo !(file2) 
file1 file3 

如果我通過一個殼表達到執行它在副殼的程序,操作者將導致錯誤。這裏的直接運行一個子shell測試(在這裏我從另一個目錄執行,以確保膨脹不會過早地發生):

~/test$ cd .. 
~$ bash -c "cd test ; echo *" 
file1 file2 file3 
~$ bash -c "cd test ; echo !(file2)" # expected output: file1 file3 
bash: -c: line 0: syntax error near unexpected token `(' 
bash: -c: line 0: `cd test ; echo !(file2)' 

我已經試過各種逃避的,但沒有我已經拿出了正確的工作。我也懷疑extglob不在一個子shell設置,但事實並非如此:

~$ bash -c "shopt -s extglob ; cd test ; echo !(file2)" 
bash: -c: line 0: syntax error near unexpected token `(' 
bash: -c: line 0: `cd test ; echo !(file2)' 

任何解決方案感謝!

回答

3
 
$ bash -O extglob -c 'echo !(file2)' 
file1 file3 
1

嗯,我沒有與extglob任何真正的遭遇,但我可以得到它通過在eval包裹echo工作:

$ bash -c 'shopt -s extglob ; cd test ; eval "echo !(file2)"' 
file1 file3 
3

這裏的另一種方式,如果你想要避免eval,並且您需要能夠在子外殼內打開和關閉extglob。只要把你的模式在一個變量:

bash -c 'shopt -s extglob; cd test; patt="!(file2)"; echo $patt; shopt -u extglob; echo $patt' 

給出了這樣的輸出:

file1 file3 
!(file2) 

表明extglob設置和取消。如果第一個echo的報價在$patt左右,那麼它就會像第二個echo(可能應該有引號)一樣吐出模式。

4

bash在執行之前解析每一行,因此當bash驗證通配模式語法時,「shop -s extglob」不會生效。該選項不能在同一行中啓用。這就是爲什麼「bash -O extglob -c'xyz'」解決方案(來自Randy Proctor)的工作原理和要求。

相關問題