cambiare IFS temporaneamente prima di un ciclo for [duplicato]

Aug 16 2020

So che SHELLconsente l'assegnazione delle variabili immediatamente prima di un comando, in modo tale che IFS=":" read a b c d <<< "$here_string"funzioni ...

Quello che mi chiedevo è che tali assegnazioni non funzionano quando vengono eseguite con istruzioni composte come i cicli? Ho provato qualcosa di simile IFS=":" for i in $PATH; do echo $i; donema risulta in un errore di sintassi. Potevo sempre fare qualcosa del genere oldIFS="$IFS"; IFS=":"; for....; IFS="$oldIFS", ma volevo sapere se c'era un modo per far funzionare tali assegnazioni inline per istruzioni composte come i forloop?

Risposte

3 Quasímodo Aug 16 2020 at 21:12

forè una parola riservata e come tale segue regole speciali :

Le seguenti parole devono essere riconosciute come parole riservate:

! {} case do done elif else esac fi for if in then until while

Questo riconoscimento avverrà solo quando nessuno dei caratteri è citato e quando la parola è usata come:

  • La prima parola di un comando

  • La prima parola che segue una delle parole riservate diversa da case , for , o in

  • La terza parola in un comando case (solo in è valido in questo caso)

  • La terza parola in un comando for (solo in e do sono validi in questo caso)

Se provi

IFS=":" for i in $PATH; do echo $i; done

, secondo le regole precedenti, questo non è un forciclo, poiché la parola chiave non è la prima parola del comando. Ma il tuo intento potrebbe essere raggiunto con

IFS=: printf '%s\n' $PATH

$PATHsubisce la suddivisione delle parole :come previsto e ogni parola risultante viene stampata da printf, seguita da una nuova riga.


Potresti avere familiarità con questo valido approccio:

while IFS= read -r line; do

whileè la prima parola del comando e l' IFSassegnazione si applica read, quindi è tutto OK.