Explique el comando de shell: shift $ (($ optind - 1))

30

No soy un chico de Linux, pero estoy atrapado en un script que tengo que leer para mi proyecto. Entonces, ¿alguien puede ayudarme en lo que hace este comando?

shift $(($optind - 1))
Gaurav Pant
fuente
3
Como se indica a continuación, OPTIND debe estar en mayúscula y el '$' dentro del paréntesis es opcional.
DarkHeart

Respuestas:

49

shift $((OPTIND-1))(la nota OPTINDes mayúscula) normalmente se encuentra inmediatamente después de un getopts whilebucle. $OPTINDes la cantidad de opciones encontradas por getopts.

Como pauljohn32 menciona en los comentarios, estrictamente hablando, OPTINDda la posición del siguiente argumento de línea de comando.

Del Manual de referencia de GNU Bash :

getopts optstring name [args]

getoptses utilizado por los scripts de shell para analizar parámetros posicionales. optstringcontiene los caracteres de opción que se reconocerán; Si un carácter va seguido de dos puntos, se espera que la opción tenga un argumento, que debe estar separado de él por espacios en blanco. Los dos puntos (':') y el signo de interrogación ('?') No se pueden usar como caracteres de opción. Cada vez que se invoca, getoptscoloca la siguiente opción en el nombre de la variable de shell, inicializando namesi no existe, y el índice del siguiente argumento que se procesará en la variable OPTIND. OPTINDse inicializa a 1 cada vez que se invoca el shell o un script de shell. Cuando una opción requiere un argumento, getopts coloca ese argumento en la variable OPTARG. El shell no se reiniciaOPTIND automáticamente; debe reiniciarse manualmente entre varias llamadas getoptsdentro de la misma invocación de shell si se va a utilizar un nuevo conjunto de parámetros.

Cuando se encuentra el final de las opciones, getoptssale con un valor de retorno mayor que cero. OPTINDse establece en el índice del primer argumento sin opción y el nombre se establece en '?'.

getoptsnormalmente analiza los parámetros posicionales, pero si se dan más argumentos args,getopts analiza en su lugar.

shift n
elimina n cadenas de la lista de parámetros posicionales. Asíshift $((OPTIND-1)) elimina todas las opciones que se han analizado getoptsde la lista de parámetros y, después de ese punto, $1se referirá al primer argumento sin opción pasado al script.

Actualizar

Como menciona mikeserv en el comentario, shift $((OPTIND-1))puede ser inseguro. Para evitar la división de palabras no deseada, etc., todas las expansiones de parámetros deben ser entre comillas dobles. Entonces la forma segura para el comando es

shift "$((OPTIND-1))"

PM 2Ring
fuente
Parece que esto solo funcionará correctamente si todas las opciones ocurren antes de cualquier argumento posicional restante. ¿Correcto?
Steve Jorgensen
@ SteveJorgensen: Sí, eso es correcto. OTOH, poner opciones después de argumentos que no son opciones va en contra de la convención sh / bash. En general, los primeros argumentos que no comienzan con un guión significan el final de las opciones, y los argumentos posteriores que comienzan con un guión no se consideran opciones. No todos los programas se adhieren a esta convención, pero hace la vida mucho más simple si lo hace. :)
PM 2Ring
@SteveJorgensen: (cont.) Este tema se trata brevemente en ¿Por qué algunas utilidades analizan los operandos antes que las opciones? . Como menciona el comentario de Gilles a la respuesta de Celada, algunos programas (como find) pueden parecer que permiten opciones después de no opciones, pero no: tienen operandos que comienzan con un guión.
PM 2Ring
Gracias por esa información (y la edición) @mosvy Eso es bastante inusual IFS, pero es mejor prevenir que curar. ;)
PM 2 Timbre
@roaima if IFS=0123456789 , shift $((OPTIND-1))(sin comillas) se convertirá en lo shift ""que se ignorará en silencio (en ksh) o generará un error (en bashy dash).
mosvy
8

$((...))solo calcula cosas. En su caso, toma el valor de $optinty resta 1.

shiftelimina los parámetros posicionales. En su caso, elimina los optint-1parámetros.

Para obtener más información echar un vistazo a help getopts, help shift, ver man bashpara "expansión aritmética", y especialmente Google para getopts.

michas
fuente