<Precedenti | Contenuti | Succ.>
IFS
Normalmente, la shell esegue la suddivisione in parole sull'input fornito a read. Come abbiamo visto, ciò significa che più parole separate da uno o più spazi diventano elementi separati sulla riga di input e vengono assegnate a variabili separate da read. Questo comportamento è configurato da una variabile di shell denominata IFS (per separatore di campo interno). Il valore predefinito di IFS contiene uno spazio, una tabulazione e un carattere di nuova riga, ognuno dei quali separerà gli elementi l'uno dall'altro.
Possiamo regolare il valore di IFS per controllare la separazione dei campi in ingresso a read. Ad esempio, il /etc/passwd Il file contiene righe di dati che utilizzano il carattere due punti come separatore di campo. Modificando il valore di IFS a due punti singoli, possiamo usare read per inserire il contenuto di /etc/passwd e separare correttamente i campi in variabili diverse. Qui abbiamo uno script che fa proprio questo:
#! / Bin / bash
# read-ifs: legge i campi da un file FILE=/etc/passwd
#! / Bin / bash
# read-ifs: legge i campi da un file FILE=/etc/passwd
read -p "Inserisci un nome utente > " nome_utente info_file=$(grep "^$nome_utente:" $FILE) if [ -n "$info_file" ]; poi
IFS=":" read user pw uid gid name home shell <<< "$file_info" echo "User = '$user'"
echo "UID = '$uid'"
echo "GID = '$gid'" echo "Nome completo = '$nome'" echo "Home Dir. = '$home'" echo "Shell = '$shell'"
altro
echo "Nessun utente di questo tipo '$user_name'" >&2 exit 1
fi
read -p "Inserisci un nome utente > " nome_utente info_file=$(grep "^$nome_utente:" $FILE) if [ -n "$info_file" ]; poi
IFS=":" read user pw uid gid name home shell <<< "$file_info" echo "User = '$user'"
echo "UID = '$uid'"
echo "GID = '$gid'" echo "Nome completo = '$nome'" echo "Home Dir. = '$home'" echo "Shell = '$shell'"
altro
echo "Nessun utente di questo tipo '$user_name'" >&2 exit 1
fi
Questo script richiede all'utente di inserire il nome utente di un account sul sistema, quindi visualizza i diversi campi trovati nel record dell'utente nel /etc/passwd file. Lo script contiene due righe interessanti. Il primo è:
file_info=$(grep "^$nome_utente:" $FILE)
Questa riga assegna i risultati di a grep comando alla variabile file_info. L'espressione regolare usata da grep assicura che il nome utente corrisponderà solo a una singola riga nel /etc/passwd file.
La seconda riga interessante è questa:
IFS=":" read user pw uid gid name home shell <<< "$file_info"
La linea si compone di tre parti: un'assegnazione variabile, a read comando con un elenco di nomi di variabili come argomenti e uno strano nuovo operatore di reindirizzamento. Esamineremo prima l'assegnazione delle variabili.
La shell consente di eseguire una o più assegnazioni di variabili immediatamente prima di un comando. Queste assegnazioni alterano l'ambiente per il comando che segue. L'effetto dell'incarico è temporaneo; cambiando solo l'ambiente per la durata del comando. Nel nostro caso, il valore di IFS viene modificato in un carattere due punti. In alternativa, avremmo potuto codificarlo in questo modo:
OLD_IFS="$IFS" IFS=":"
leggi utente pw uid gid nome home shell <<< "$file_info" IFS="$OLD_IFS"
dove memorizziamo il valore di IFS, assegnare un nuovo valore, eseguire il read comando, quindi ripristina IFS al suo valore originario. Chiaramente, anteponendo l'assegnazione della variabile a
il comando è un modo più conciso di fare la stessa cosa.
. << l'operatore indica a qui stringa. Una stringa qui è come un documento qui, solo più corta, costituita da una singola stringa. Nel nostro esempio, la riga di dati da
Il file /etc/passwd viene inviato all'input standard del comando read. Potremmo vincere-
der perché è stato scelto questo metodo piuttosto obliquo piuttosto che:
echo "$file_info" | IFS=":" read user pw uid gid name home shell
beh, c'è un motivo...
Non puoi leggere la pipe
Mentre l' read il comando normalmente prende l'input dall'input standard, non puoi farlo:
echo "pippo" | leggere
Ci aspetteremmo che funzioni, ma non è così. Il comando sembrerà avere successo ma il REPLY variabile sarà sempre vuota. Perchè è questo?
La spiegazione ha a che fare con il modo in cui la shell gestisce le pipeline. In bash (e altre conchiglie come sh), le pipeline creano subshell. Queste sono copie della shell e del suo ambiente che vengono utilizzate per eseguire il comando nella pipeline. Nel nostro esempio sopra, read viene eseguito in una subshell.
Le subshell nei sistemi Unix-like creano copie dell'ambiente che i processi possono utilizzare durante l'esecuzione. Al termine dei processi, la copia dell'ambiente viene distrutta. Ciò significa che una subshell non può mai alterare l'ambiente del suo processo genitore. read assegna variabili, che poi diventano parte dell'ambiente. Nell'esempio sopra, read assegna il valore “pippo” alla variabile RISPONDERE nell'ambiente della sua subshell, ma quando il comando termina, la subshell e il suo ambiente vengono distrutti e l'effetto dell'assegnazione viene perso.
L'utilizzo di stringhe qui è un modo per aggirare questo comportamento. Un altro metodo è discusso nel capitolo 36.