2012-08-29 39 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