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, solo I , am e a 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 e string 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à stampata a 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 di test per il quale I 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 a apt-get , mentre citando invierà la stringa $packs come un singolo argomento e quindi apt-get proverà a installare un pacchetto denominato apache2 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.



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow