2010-05-20 6 views
23

En el medio de un script, quiero verificar si se pasó un indicador determinado en la línea de comando. A continuación se hace lo que yo quiero, pero parece feo:Manera correcta de buscar un indicador de línea de comando en bash

if echo $* | grep -e "--flag" -q 
then 
    echo ">>>> Running with flag" 
else 
    echo ">>>> Running without flag" 
fi 

¿Hay una mejor manera?

Nota: explícitamente no quiero quiero enumerar todos los indicadores en un interruptor/getopt. (En este caso, cualquiera de estos elementos se convertiría en la mitad o más de la secuencia de comandos completa. También los cuerpos de if si establecen un conjunto de vars)

Respuesta

4

Puede usar la palabra clave getopt en bash.

De http://aplawrence.com/Unix/getopts.html:

getopt

Este es un archivo ejecutable independiente que ha existido desde hace mucho tiempo. Las versiones anteriores carecen de la capacidad de manejar los argumentos entrecomillados (foo a "this no funcionará" c) y las versiones que pueden, lo hacen torpemente. Si tiene con una versión de Linux reciente, su "getopt" puede hacerlo; SCO OSR5, Mac OS X 10.2.6 y FreeBSD 4.4 tiene una versión anterior que no.

El simple uso de "getopt" se muestra en este mini-guión:

#!/bin/bash 
echo "Before getopt" 
for i 
do 
    echo $i 
done 
args=`getopt abc:d $*` 
set -- $args 
echo "After getopt" 
for i 
do 
    echo "-->$i" 
done 
+0

Es mejor usar el 'getopts' incorporado en lugar del' getopt' externo. –

+0

@Dennis: 'getopts' admite nombres de opciones largos como' --flag'? – indiv

+0

@indiv: Oh, lo siento, pasé por alto ese requisito. Usaría una declaración 'case' antes de usar' getopt'. Ver [esto] (http://aplawrence.com/Unix/getopts.html) para una comparación de 'getopt' y' getopts'. –

4

Me suelen ver este hecho con una declaración de caso. He aquí un extracto de la escritura git-repack:

while test $# != 0 
do 
    case "$1" in 
    -n) no_update_info=t ;; 
    -a) all_into_one=t ;; 
    -A) all_into_one=t 
     unpack_unreachable=--unpack-unreachable ;; 
    -d) remove_redundant=t ;; 
    -q) GIT_QUIET=t ;; 
    -f) no_reuse=--no-reuse-object ;; 
    -l) local=--local ;; 
    --max-pack-size|--window|--window-memory|--depth) 
     extra="$extra $1=$2"; shift ;; 
    --) shift; break;; 
    *) usage ;; 
    esac 
    shift 
done 

Tenga en cuenta que este le permite comprobar de ambas banderas cortas y largas. En este caso, se crean otras opciones utilizando la variable extra.

+0

Creo que tiene que eliminar la última instrucción 'shift', justo después de 'esac'. Al menos en mi máquina no funciona si está presente. –

37

Una alternativa a lo que está haciendo:

if [[ $* == *--flag* ]] 

Ver también BashFAQ/035.

+0

¿Eso no recogerá también los falsos positivos? p.ej. si busca '' -f * 'coincidirá con' --force', '-fish',' --update-files', '-w-t-f'etc – nathanchere

+0

@nathanchere: la elección cuidadosa de la cadena de coincidencia es importante. Tenga en cuenta que su ejemplo permite todas las coincidencias que enumera, pero el mío deja muchas menos posibilidades de falsos positivos. Dado el requisito de OP para una solución simple, la mina encaja bastante bien. De lo contrario, use getopt o getopts. –

+0

Exactamente mi punto.El mío fue un ejemplo intencionalmente simplificado, pero aún demuestra el mismo problema con el tuyo. p.ej. si usa '* - flag *', coincidirá con '--flag',' --flags-off', es decir, es una solución descuidada – nathanchere

Cuestiones relacionadas