L'espansione dei parametri su $ @ non è supportata dalla shell sh?


8

Ho pubblicato una risposta a una domanda su AU e ho scoperto che l'espansione dei parametri su $@non funziona con la shshell:

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

ma funziona benissimo in bash. Questo comportamento previsto della shshell è e come posso eseguire l'espansione lì?

Inoltre, so che con l' -n1opzione di xargsposso passare solo una riga al comando alla volta, ma ero interessato a sapere se è shpossibile espandere $@:

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

infile contiene:

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

Risposte:


12

Sì, il trattino sembra essere poco utile qui. Anche se non è esente da colpa, a rigor di termini, come ${@%...}è specificato da POSIX :

Le seguenti quattro varietà di espansione dei parametri prevedono l'elaborazione della sottostringa. [...] Se il parametro è ' #', ' *' o ' @', il risultato dell'espansione non è specificato.

È strano però, se un'espansione del genere modifica la fine di un parametro posizionale, rilascia i seguenti. Ma non se in realtà non modifica la fine:

$ 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 e Zsh sembrano tutti in grado di gestire "${@#...}"ed "${@%...}"elaborare ogni parametro posizionale in modo indipendente, il che sembrerebbe la cosa utile da fare.

Suppongo che l'evidente soluzione alternativa dashsia quella di rendere la modifica un argomento alla volta:

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

Per quello che vale, il comportamento delle espansioni di rimozione prefisso / suffisso utilizzate $*varia anche tra le shell. Bash e ksh sembrano modificare prima i parametri e unirli successivamente, mentre Zsh e dash uniscono prima i parametri e modificano la stringa concatenata:

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

sound shpensa che $@sia un singolo parametro per l'intero file (o si spezzerà in più se supera ARG_MAX) e farà l'espansione sull'unico argomento.
αғsнιη,

1
Nota anche che pdksh e derivati ​​ti danno un Bad substitutionerrore su quel codice. Perché ${*%pattern}, vedi alcune variazioni nel comportamento in cose come"$shell" -c 'printf "<%s>\n" "${*%x*}"' sh ax by
Stéphane Chazelas,

1
@ αғsнιη, non è così semplice. notare il secondo esempio in cui l'espansione lascia i parametri posizionali come parole separate. E non credo che ARG_MAXci sia, quell'elaborazione è interna alla shell.
ilkkachu,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.