Significado de [“$ {1: 0: 1}” = '-']

18

Tengo el siguiente script para iniciar un proceso MySQL:

if [ "${1:0:1}" = '-' ]; then
    set -- mysqld_safe "$@"
fi

if [ "$1" = 'mysqld_safe' ]; then
    DATADIR="/var/lib/mysql"
...

¿Qué significa 1: 0: 1 en este contexto?

usuario3521621
fuente
1
Realmente me gustaría saber la respuesta, pero creo que esta es una pregunta un poco limitada para SF. Estoy votando para migrarlo al sitio Unix.
Massimo

Respuestas:

19

Es una prueba para una -opción de argumento discontinuo, aparentemente. Es un poco extraño, de verdad. Utiliza una bashexpansión no estándar en un intento de extraer el primer y solo el primer personaje $1. El 0es el índice del carácter principal y la 1longitud de la cadena. De manera [ testsimilar, también podría ser:

[ " -${1#?}" = " $1" ]

Sin testembargo, ninguna de las comparaciones es particularmente adecuada , ya que también interpreta -argumentos discontinuos, razón por la cual uso el espacio inicial allí.

La mejor manera de hacer este tipo de cosas, y la forma en que generalmente se hace, es:

case $1 in -*) mysqld_safe "$@"; esac
mikeserv
fuente
1
Cerca; el número que sigue al segundo colon ${1:0:1}es una longitud, no un índice.
chepner
En una forma del bash con [[: [[ $1 == -* ]].
Arthur2e5
2
Personalmente, no creo que eso -sea ​​un problema testaquí. POSIX ofrece definiciones de los significados por conteo de argumentos. Como no existe tal opción que tome dos argumentos, debería ser seguro escribirlo en bruto.
Arthur2e5
@ Arthur2e5: tiene razón, no deberían ser un problema, y ​​muy probablemente no sean problemáticos en absoluto. sigue siendo una forma extraña de hacerlo, simplemente no encaja bien. ¿qué [[ : [[hacer?
mikeserv
1
@mikeserv Bueno, deberías mirar la página web (si estás leyendo esto desde otro lugar) .. Mi comentario fue como 'con START_CODE [[END_CODE: START_CODE [[$ 1 == - *]] END_CODE'. El primero [[es solo el nombre de sintaxis, y los dos puntos son solo una puntuación.
Arthur2e5
11

Esto va a tomar una subcadena del $10 al 1er carácter. Entonces obtendrá el primer carácter y solo el primer carácter de la cadena.

Desde la bashpágina del manual 3.2:

  ${parameter:offset}
  ${parameter:offset:length}
          Substring  Expansion.   Expands  to  up to length characters of
          parameter starting at the character specified  by  offset.   If
          length is omitted, expands to the substring of parameter start-
          ing at the character specified by offset.   length  and  offset
          are  arithmetic  expressions (see ARITHMETIC EVALUATION below).
          length must evaluate to a number greater than or equal to zero.
          If  offset  evaluates  to a number less than zero, the value is
          used as an offset from the end of the value of  parameter.   If
          parameter  is  @,  the  result  is length positional parameters
          beginning at offset.  If parameter is an array name indexed  by
          @ or *, the result is the length members of the array beginning
          with ${parameter[offset]}.  A negative offset is taken relative
          to  one  greater than the maximum index of the specified array.
          Note that a negative offset must be separated from the colon by
          at  least  one space to avoid being confused with the :- expan-
          sion.  Substring indexing is zero-based unless  the  positional
          parameters are used, in which case the indexing starts at 1.
polluelos
fuente
6

Está probando que el primer carácter del primer argumento $1es un guión -.

El 1: 0: 1 son los valores para la expansión de parámetro: ${parameter:offset:length}.

Eso significa:

  • Nombre: el parámetro nombrado 1, es decir:$1
  • Inicio: desde el primer carácter 0(numerado desde 0).
  • Longitud: para 1 personaje.

En resumen: el primer carácter del primer parámetro posicional $1.
Esa expansión de parámetros está disponible en ksh, bash, zsh (al menos).


Si desea cambiar la línea de prueba:

[ "${1:0:1}" = "-" ]

Opciones de golpe

Otras soluciones bash más seguras pueden ser:

[[ $1 =~ ^- ]]
[[ $1 == -* ]]

Más seguro porque esto no tiene problemas con las citas (no se ejecuta división dentro [[)

POSIXly opciones.

Para conchas más viejas y menos capaces, se podría cambiar a:

[ "$(echo $1 | cut -c 1)" = "-" ]
[ "${1%%"${1#?}"}"        = "-" ]
case $1 in  -*) set -- mysqld_safe "$@";; esac

Solo el comando case es más resistente a las citas incorrectas.


fuente