Tengo un script simple donde el primer argumento está reservado para el nombre del archivo, y todos los demás argumentos opcionales deben pasarse a otras partes del script.
Usando Google encontré este wiki , pero proporcionó un ejemplo literal:
echo "${@: -1}"
No puedo hacer que nada más funcione, como:
echo "${@:2}"
o
echo "${@:2,1}"
Recibo "Mala sustitución" de la terminal.
¿Cuál es el problema y cómo puedo procesar todos menos el primer argumento pasado a un script bash?
"{@:2}"
que no funcione, por lo que la respuesta correcta coincide con la anterior.Respuestas:
Utilizar este:
La siguiente sintaxis:
funcionaría bien, pero no se recomienda, porque como ya explicó @Gordon , que al usarlo
*
, ejecuta todos los argumentos juntos como un solo argumento con espacios, mientras@
conserva los descansos entre ellos (incluso si algunos de los argumentos contienen espacios) ) No hace la diferencia conecho
, pero es importante para muchos otros comandos.fuente
#!/usr/bin/env sh
por eso tuve problemas. Su ejemplo funciona bien, igual que el anterior, después de que eliminé ese shebang"${@:2}"
lugar: el uso*
ejecuta todos los argumentos juntos como un solo argumento con espacios, mientras@
conserva los descansos entre ellos (incluso si algunos de los argumentos contienen espacios). La diferencia no se nota conecho
, pero es importante para muchas otras cosas.echo
es perdonar lo suficiente como para concatenarlos por ti; otros comandos podrían no ser tan agradables. No solo use uno u otro: aprenda la diferencia entre*
y@
, y cuándo usar cada uno. Deberías estar usándolos casi por igual. Un buen ejemplo de cuándo esto será un problema: si$3
contiene un salto de línea (\n
), se reemplazará con un espacio, siempre que tenga una$IFS
variable predeterminada .echo
solo utiliza como un ejemplo - en cuyo caso se deben no pueden ejecutar juntos. En mi experiencia, las situaciones en las que desea que se ejecuten juntas son raras (consulte esta pregunta para ver un ejemplo ) y"$@"
casi siempre es lo que desea. Además, el problema que menciona con un salto de línea solo ocurre si$@
(o$*
) no está entre comillas dobles.$*
bastante frecuencia en mis scripts.Si quieres una solución que también funcione en
/bin/sh
probarshift [n]
desplaza los parámetros posicionales n veces. Ashift
establece el valor de$1
al valor de$2
, el valor de$2
al valor de$3
, y así sucesivamente, disminuyendo el valor de$#
uno.fuente
foo=shift
no hace lo que esperaba.foo=$(shift)
shift
(en shell) no tiene ningún resultado. Simplemente descarta$1
y cambia todo hacia abajo. 2)$(...)
inicia una subshell, que tiene sus propios argumentos locales. Cambia los argumentos en la subshell, lo que no afecta al padresomecommand "$1" "${@:2}"
hace con este método (es decir, cambiar "en línea")?http://wiki.bash-hackers.org/scripting/posparams
Explica el uso de
shift
(si desea descartar los primeros N parámetros) y luego implementar el uso masivofuente
Encontré esto buscando algo más. Si bien la publicación parece bastante antigua, la solución más fácil en bash se ilustra a continuación (al menos bash 4) usando
set -- "${@:#}"
donde # es el número inicial del elemento de matriz que queremos conservar hacia adelante:Básicamente, el elemento
set -- "${@:3}"
emerge de los dos primeros elementos de la matriz, como el desplazamiento de Perl, y conserva todos los elementos restantes, incluido el tercero. Sospecho que también hay una manera de resaltar los últimos elementos.fuente