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
IFSnon sono stati trovati.
Ora impostiamo IFS=/
$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>
$varsi 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,ameaverranno 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\nmultilineestringverrà 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à stampataamultiline 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'
$varnon è 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 ditestper il qualeI am a string with spacesnon è 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
greprestituisce 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'
arrcon 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
$packssequenziali inviano tutti i nomi dei pacchetti separati da spazio come argomenti aapt-get, mentre citando invierà la stringa$packscome un singolo argomento e quindiapt-getproverà 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.