¿La expansión de parámetros en $ @ no es compatible con el shell sh?


8

Publiqué una respuesta a una pregunta en AU, y descubrí que la expansión de parámetros $@no funciona con el shshell:

<infile xargs -d'\n' sh -c 'echo "${@%%/*}"' _

pero funciona bien en bash. ¿Es este el comportamiento esperado del shshell, y cómo puedo realizar la expansión allí?

Además, sé que con la -n1opción de xargspuedo pasar solo una línea al comando a la vez, pero estaba interesado en si shpuedo expandir $@:

<infile xargs -d'\n' -n1 sh -c 'echo "${0%%/*}"'

infile contiene:

A1 /B1/C1
A 2/B2/C2
A3/B3/C3

Respuestas:


12

Sí, el guión parece ser menos que útil aquí. Aunque no es la culpa, en sentido estricto, como ${@%...}es especificado por POSIX :

Las siguientes cuatro variedades de expansión de parámetros proporcionan procesamiento de subcadenas. [...] Si el parámetro es ' #', ' *' o ' @', el resultado de la expansión no está especificado.

Sin embargo, es extraño, parece que si una expansión como esa modifica el final de un parámetro posicional, deja caer los siguientes. Pero no si en realidad no modifica el final:

$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%o}";'
<fo>
$ dash -c 'set -- foo bar; printf "<%s>\n" "${@%x}";'
<foo>
<bar>
$ dash -c 'set -- foo bar doo; printf "<%s>\n" "${@%r}";'
<foo>
<ba>

Bash, ksh y Zsh parecen manejar "${@#...}"y "${@%...}"procesar cada parámetro posicional de forma independiente, lo que parece lo más útil.

Supongo que la solución obvia para dashes hacer la modificación de un argumento a la vez:

for x in "$@"; do echo "${x%%/*}"; done

Por lo que vale, el comportamiento de las expansiones de eliminación de prefijos / sufijos utilizados $*también varía entre shells. Bash y ksh parecen modificar los parámetros primero y unirse a ellos después de eso, mientras que Zsh y dash unen los parámetros primero y modifican la cadena concatenada:

$ zsh -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a>
$ bash -c 'set -- ax bx; printf "<%s>\n" "${*%%x*}";'
<a b>

sonidos shpiensa que $@es un parámetro único para todo el archivo (o se romperá en múltiples si excede ARG_MAX) y se expandirá en el único argumento.
αғsнιη

1
También tenga en cuenta que pdksh y derivados le dan un Bad substitutionerror en ese código. Para ${*%pattern}, ves alguna variación en el comportamiento en cosas como"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
Stéphane Chazelas

1
@ αғsнιη, no es tan simple. observe el segundo ejemplo donde la expansión deja los parámetros posicionales como palabras separadas. Y no creo que eso ARG_MAXsuceda, ese procesamiento es interno al shell.
ilkkachu
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.