2012-08-29 10 views
11

Estoy tratando de escribir una función bash que use nocasematch sin cambiar la configuración de las personas que llaman de la opción. La definición de la función es:Make shopt change local to function

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

Antes de que yo lo llamo:

$ shopt nocasematch 
nocasematch  off 

Llámelo:

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

Como era de esperar, pero ahora nocasematch de la persona que llama ha cambiado:

$ shopt nocasematch 
nocasematch  on 

¿Hay alguna manera fácil de hacer que la opción cambie localmente a la función?

Sé que puedo verificar el valor de retorno de shopt -q pero eso significa que la función debe recordar esto y reiniciarlo antes de salir.

Respuesta

20

El cuerpo de la función puede ser cualquier comando compuesto, no solo un comando de grupo ({}). Utilizar un sub-shell:

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

Eso funciona muy bien, gracias. – Thor

+0

+1 ¡Aseado! No lo sabía. – tripleee

+11

'foo() {...}' se ve tan natural, nunca se piensa que las llaves no son parte de la sintaxis de la función, en lugar del comando compuesto comúnmente utilizado. – chepner

7

Sé que esta fecha a partir de 2012, pero también se puede hacer lo siguiente (funciona en Git Bash 1.8.4 en Windows, por lo que debería funcionar en Linux):

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

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

La opción -p simplemente imprime shopt -s extglob si extglob está activado, de lo contrario shopt -u extglob.

shopt -p imprime toda la lista de opciones.

+0

Si existe información que mejore la discusión, siempre es bienvenido. La solución que sugieres, recordar la configuración y cambiarla, es lo que estaba tratando de evitar. Debería haber sido más explícito al respecto. De todos modos, vale la pena mantener su respuesta como una buena alternativa de cómo hacerlo. +1 – Thor

+1

Para mi caso, no me importó y admito que esto podría ser tan malo como atemperar con IFS. Por otro lado, supongo que sería fácil hacer una función 'pushshopt' como si hubiera una' pushd', y usar arreglos bash para recordar la opción anterior antes de configurarlos. Como 'pushshopt + extglob -nocasematch' y' popshopt'. – NoDataFound