Bash
Scissione di parole
Ricerca…
Sintassi
- Imposta IFS su newline: IFS = $ '\ n'
- Imposta IFS su nullstring: IFS =
- Imposta IFS su / carattere: IFS = /
Parametri
Parametro | Dettagli |
---|---|
IFS | Separatore di campo interno |
-X | Stampa i comandi e i loro argomenti mentre vengono eseguiti (opzione Shell) |
Osservazioni
- La suddivisione in parole non viene eseguita durante le assegnazioni, ad es.
newvar=$var
- La divisione di parole non viene eseguita nel costrutto
[[ ... ]]
- Usa le doppie virgolette sulle variabili per impedire la divisione delle parole
Scissione con IFS
Per essere più chiari, creiamo uno script chiamato showarg
:
#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo
Ora vediamo le differenze:
$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
è diviso in 4 arg.IFS
è caratteri di spazio bianco e quindi la divisione delle parole si è verificata negli spazi
$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>
Nella suddetta divisione di parole non si è verificato perché i caratteri
IFS
non sono stati trovati.
Ora impostiamo IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
$var
si divide in 4 argomenti non in un singolo argomento.
Cosa, quando e perché?
Quando la shell esegue l' espansione dei parametri , la sostituzione di comando , l' espansione variabile o aritmetica , esegue la scansione dei confini delle parole nel risultato. Se viene trovato un limite di parole, il risultato viene diviso in più parole in quella posizione. Il limite di parola è definito da una variabile di shell IFS
(Internal Field Separator). Il valore predefinito per IFS è lo spazio, la tabulazione e la nuova riga, ovvero la divisione della parola si verifica su questi tre spazi bianchi se non viene impedita esplicitamente.
set -x
var='I am
a
multiline string'
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
Nell'esempio sopra questo è come viene eseguita la funzione fun
:
fun I am a multiline string
$var
è diviso in 5 arg, soloI
,am
ea
verranno stampati.
IFS e divisione delle parole
Vedi cosa, quando e perché se non si conosce l'affiliazione di IFS alla suddivisione in parole
impostiamo l'IFS solo sul carattere dello spazio:
set -x
var='I am
a
multiline string'
IFS=' '
fun() {
echo "-$1-"
echo "*$2*"
echo ".$3."
}
fun $var
Questa divisione delle parole sul tempo funzionerà solo sugli spazi. La fun
funzione verrà eseguita in questo modo:
fun I 'am
a
multiline' string
$var
è diviso in 3 arg.I
,am\na\nmultiline
estring
verrà stampato
Impostiamo IFS solo su newline:
IFS=$'\n'
...
Ora il fun
sarà eseguito come:
fun 'I am' a 'multiline string'
$var
è diviso in 3 arg.I am
,a
, verrà stampataa
multiline string
Vediamo cosa succede se impostiamo IFS su nullstring:
IFS=
...
Questa volta il fun
sarà eseguito in questo modo:
fun 'I am
a
multiline string'
$var
non è diviso cioè è rimasto un singolo arg.
È possibile impedire la divisione delle parole impostando l'IFS su nullstring
Un modo generale per prevenire la divisione delle parole è usare la doppia citazione:
fun "$var"
impedirà la divisione delle parole in tutti i casi discussi sopra, vale a dire che la funzione fun
verrà eseguita con un solo argomento.
Cattivi effetti della divisione delle parole
$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = $a ]
stato interpretato come[ I am a string with spaces = I am a string with spaces ]
.[
è il comando ditest
per il qualeI am a string with spaces
non è un singolo argomento, piuttosto è 6 argomenti !!
$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match
[ $a = something ]
stato interpretato come[ I am a string with spaces = something ]
$ [ $(grep . file) = 'something' ]
bash: [: too many arguments
Il comando
grep
restituisce una stringa multilinea con spazi, quindi puoi solo immaginare quanti argomenti ci siano ...: D
Scopri cosa, quando e perché per le basi.
Utilità della divisione delle parole
Vi sono alcuni casi in cui la suddivisione in parole può essere utile:
Riempimento dell'array:
arr=($(grep -o '[0-9]\+' file))
Questo riempirà l'
arr
con tutti i valori numerici trovati nel file
Andare in loop tra parole separate dallo spazio:
words='foo bar baz'
for w in $words;do
echo "W: $w"
done
Produzione:
W: foo
W: bar
W: baz
Passando parametri separati da spazi che non contengono spazi bianchi:
packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs
o
packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs
Questo installerà i pacchetti. Se si raddoppiano i
$packs
, verrà generato un errore.
I
$packs
sequenziali inviano tutti i nomi dei pacchetti separati da spazio come argomenti aapt-get
, mentre citando invierà la stringa$packs
come un singolo argomento e quindiapt-get
proverà a installare un pacchetto denominatoapache2 php php-mbstring php-mysql
(per il primo) che ovviamente non esiste
Scopri cosa, quando e perché per le basi.
Divisione per modifiche del separatore
Possiamo semplicemente fare una semplice sostituzione dei separatori dallo spazio alla nuova linea, come nell'esempio seguente.
echo $sentence | tr " " "\n"
Dividerà il valore della sentence
variabile e lo mostrerà riga per riga rispettivamente.