Szukaj…


Składnia

  • Ustaw IFS na nowy wiersz: IFS = $ '\ n'
  • Ustaw IFS na nullstring: IFS =
  • Ustaw IFS na / character: IFS = /

Parametry

Parametr Detale
IFS Separator pola wewnętrznego
-x Drukuj polecenia i ich argumenty podczas ich wykonywania (opcja Shell)

Uwagi

  • Podział słów nie jest wykonywany podczas przypisań, np. newvar=$var
  • Dzielenie wyrazów nie jest wykonywane w konstrukcie [[ ... ]]
  • Użyj podwójnych cudzysłowów na zmiennych, aby zapobiec dzieleniu słów

Podział za pomocą IFS

Aby być bardziej przejrzystym, stwórzmy skrypt o nazwie showarg :

#!/usr/bin/env bash
printf "%d args:" $#
printf " <%s>" "$@"
echo

Zobaczmy teraz różnice:

$ var="This is an example"
$ showarg $var
4 args: <This> <is> <an> <example>

$var jest podzielony na 4 argumenty. IFS jest znakami spacji, dlatego dzielenie słów występowało w spacjach

$ var="This/is/an/example"
$ showarg $var
1 args: <This/is/an/example>

W powyższym przypadku nie doszło do podziału słów, ponieważ nie znaleziono znaków IFS .

Teraz IFS=/

$ IFS=/
$ var="This/is/an/example"
$ showarg $var
4 args: <This> <is> <an> <example>

$var dzieli się na 4 argumenty, a nie jeden argument.

Co, kiedy i dlaczego?

Gdy powłoka wykonuje interpretację parametrów , podstawianie poleceń , interpretację zmiennych lub arytmetyki , skanuje w poszukiwaniu granic słów. Jeśli zostanie znaleziona granica słowa, wynik zostanie podzielony na wiele słów w tej pozycji. Granica słowa jest zdefiniowana przez zmienną powłoki IFS (Internal Field Separator). Domyślnymi wartościami dla IFS są spacja, tabulator i nowa linia, tzn. Dzielenie słów nastąpi na tych trzech białych znakach, jeśli nie zostanie to wyraźnie zabronione.

set -x
var='I am
a
multiline string'
fun() {
    echo "-$1-"
    echo "*$2*"
    echo ".$3."
}
fun $var

W powyższym przykładzie działa funkcja fun :

fun I am a multiline string

$var jest podzielony na 5 args, tylko I , am i zostanie wydrukowany. a

IFS i dzielenie słów

Zobacz, co, kiedy i dlaczego, jeśli nie wiesz o powiązaniu IFS z dzieleniem słów

ustawmy IFS tylko na znak spacji:

set -x
var='I am
a
multiline string'
IFS=' '
fun() {
    echo "-$1-"
    echo "*$2*"
    echo ".$3."
}
fun $var

Tym razem dzielenie słów działa tylko na spacje. Funkcja fun zostanie wykonana w następujący sposób:

fun I 'am
a
multiline' string

$var jest podzielony na 3 argumenty. I , am\na\nmultiline i string zostanie wydrukowany

Ustawmy IFS tylko na nową linię:

IFS=$'\n'
...

Teraz fun zostanie wykonana w następujący sposób:

fun 'I am' a 'multiline string'

$var jest podzielony na 3 argumenty. I am , , a multiline string zostanie wydrukowany

Zobaczmy, co się stanie, jeśli ustawimy IFS na nullstring:

IFS=
...

Tym razem fun zostanie wykonana w następujący sposób:

fun 'I am
a
multiline string'

$var nie jest podzielona, tzn. pozostała pojedynczym argumentem.

Możesz zapobiec dzieleniu słów, ustawiając IFS na nullstring

Ogólnym sposobem zapobiegania dzieleniu słów jest użycie podwójnego cudzysłowu:

fun "$var"

zapobiegnie dzieleniu słów we wszystkich przypadkach omówionych powyżej, tj. funkcja fun będzie wykonywana tylko z jednym argumentem.

Złe efekty dzielenia słów

$ a='I am a string with spaces'
$ [ $a = $a ] || echo "didn't match"
bash: [: too many arguments
didn't match

[ $a = $a ] zostało zinterpretowane jako [ I am a string with spaces = I am a string with spaces ] . [ to polecenie test dla którego I am a string with spaces nie jest pojedynczym argumentem, a raczej 6 argumentami !!

$ [ $a = something ] || echo "didn't match"
bash: [: too many arguments
didn't match

[ $a = something ] interpretowano jako [ I am a string with spaces = something ]

$ [ $(grep . file) = 'something' ]
bash: [: too many arguments

Polecenie grep zwraca łańcuch wielowierszowy ze spacjami, abyś mógł sobie wyobrazić, ile jest argumentów ...: D

Zobacz, co, kiedy i dlaczego podstawy.

Przydatność podziału słów

W niektórych przypadkach dzielenie słów może być przydatne:

Wypełnianie tablicy:

arr=($(grep -o '[0-9]\+' file))

Spowoduje to wypełnienie arr wszystkimi wartościami liczbowymi znalezionymi w pliku

Pętle przez słowa oddzielone spacjami:

words='foo bar baz'
for w in $words;do
    echo "W: $w"
done

Wynik:

W: foo
W: bar
W: baz

Przekazywanie parametrów oddzielonych spacją, które nie zawierają białych spacji:

packs='apache2 php php-mbstring php-mysql'
sudo apt-get install $packs

lub

packs='
apache2
php
php-mbstring
php-mysql
'
sudo apt-get install $packs

Spowoduje to zainstalowanie pakietów. Jeśli podwójnie zacytujesz $packs , spowoduje to błąd.

Unquoetd $packs wysyła wszystkie nazwy pakietów rozdzielonych spacjami jako argumenty do apt-get , podczas gdy cytowanie wyśle ciąg $packs jako pojedynczy argument, a następnie apt-get spróbuje zainstalować pakiet o nazwie apache2 php php-mbstring php-mysql (dla pierwszego), który oczywiście nie istnieje

Zobacz, co, kiedy i dlaczego podstawy.

Podział według zmian separatora

Możemy po prostu dokonać prostej zamiany separatorów z odstępu na nowy wiersz, jak w poniższym przykładzie.

echo $sentence | tr " " "\n"

Dzieli wartość sentence zmiennego i pokazuje odpowiednio wiersz po wierszu.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow