2012-08-29 67 views
11

我正在嘗試編寫一個使用nocasematch而不更改該選項的調用者設置的bash功能。該函數的定義是:使Shopt變更爲本地功能

is_hello_world() { 
    shopt -s nocasematch 
    [[ "$1" =~ "hello world" ]] 
} 

之前,我把它叫做:

$ shopt nocasematch 
nocasematch  off 

稱之爲:

$ is_hello_world 'hello world' && echo Yes 
Yes 
$ is_hello_world 'Hello World' && echo Yes 
Yes 

正如預期的那樣,但現在的呼叫者的nocasematch發生了變化:

$ shopt nocasematch 
nocasematch  on 

是否有任何簡單的方法可以使選項更改爲本地函數?

我知道我可以檢查shopt -q的返回值,但這仍然意味着函數應該記住這一點,並在退出之前重置它。

回答

20

函數體可以是任何複合命令,而不僅僅是一個組命令({})。使用一個子shell:

is_hello_world() (
    shopt -s nocasematch 
    [[ "$1" =~ "hello world" ]] 
) 
+0

很好用,謝謝。 – Thor

+0

+1整潔!我不知道。 – tripleee

+11

'foo(){...}'看起來很自然,你從不認爲花括號不是函數語法的一部分,而不是最常用的複合命令。 – chepner

7

我知道從2012年這個職位日期,但你也可以做(在Windows Git中的Bash 1.8.4的作品,所以它應該工作在Linux上)以下內容:

function foobar() { 
    local old=$(shopt -p extglob) 
    shopt -s extglob 

    ... your stuff here ... 
    eval "$old" 
} 

-p選項只需打印shopt -s extglob如果extglob打開,否則打印shopt -u extglob

shopt -p打印選項的整個列表。

+0

如果存在增強討論的信息,那麼總是受歡迎的。你所建議的解決方案,記住設置並將其改回,這正是我試圖避免的。我應該更明確一些。無論如何,值得將你的答案作爲如何解決這個問題的好選擇。 +1 – Thor

+1

對我而言,我並不關心它,我承認這可能和IFS一樣糟糕。另一方面,我認爲可以很容易地創建'pushshop'函數,就像'pushd''一樣,並且在設置它們之前使用bash數組來記住之前的選項。像'pushshopt + extglob -nocasematch'和'popshopt'。 – NoDataFound