Поиск…


Синтаксис

  • Установите IFS в новую строку: IFS = $ '\ n'
  • Установите IFS на nullstring: IFS =
  • Установите IFS в / символ: IFS = /

параметры

параметр подробности
IFS Внутренний разделитель полей
-Икс Команды печати и их аргументы по мере их выполнения (опция Shell)

замечания

  • Разделение слов не выполняется во время присвоений, например newvar=$var
  • Разделение слов не выполняется в конструкции [[ ... ]]
  • Используйте двойные кавычки для переменных, чтобы предотвратить разделение слов

Разделение с IFS

Чтобы быть более понятным, давайте создадим скрипт с именем showarg :

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

Теперь посмотрим различия:

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

$var делится на 4 аргумента. IFS - это символы пробела и, следовательно, разбиение слов происходит в пробелах

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

В предыдущем слове расщепление не произошло, потому что символы IFS не были найдены.

Теперь давайте установим IFS=/

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

$var делится на 4 аргумента, а не один аргумент.

Что, когда и почему?

Когда оболочка выполняет расширение параметра , подмену команды , переменное или арифметическое расширение , он сканирует границы слова в результате. Если какая-либо граница слова найдена, результат разбивается на несколько слов в этой позиции. Граница слова определяется переменной оболочки IFS (Internal Field Separator). Значением по умолчанию для IFS являются пробел, табуляция и новая строка, то есть разделение слов будет происходить на этих трех символах пробела, если это не будет предотвращено явно.

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

В приведенном выше примере это то, как выполняется функция fun :

fun I am a multiline string

$var делится на 5 аргументов, будет напечатан только I , am и a .

IFS & разбиение слов

Посмотрите, что, когда и почему, если вы не знаете о присоединении IFS к разбиению слов

давайте зададим IFS только символу пробела:

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

Это расщепление слова будет работать только на пространствах. Функция fun будет выполнена следующим образом:

fun I 'am
a
multiline' string

$var делится на 3 аргумента. I , am\na\nmultiline и string будет напечатана

Давайте установим IFS только для новой строки:

IFS=$'\n'
...

Теперь fun будет выполнена как:

fun 'I am' a 'multiline string'

$var делится на 3 аргумента. I am , a , multiline string будет напечатана

Давайте посмотрим, что произойдет, если мы установим IFS в nullstring:

IFS=
...

На этот раз fun будет выполнена следующим образом:

fun 'I am
a
multiline string'

$var не разделяется, т. е. остается одним аргументом.

Вы можете предотвратить разбиение слов, установив IFS в nullstring

Общий способ предотвращения разделения слов - использовать двойную кавычку:

fun "$var"

будет предотвращать расщепление слов во всех рассмотренных выше случаях, т. е. функция fun будет выполняться только с одним аргументом.

Плохие эффекты расщепления слов

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

[ $a = $a ] интерпретируется как [ I am a string with spaces = I am a string with spaces ] . [ это test команда, для которой I am a string with spaces - это не один аргумент, а 6 аргументов!

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

[ $a = something ] интерпретируется как [ I am a string with spaces = something ]

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

Команда grep возвращает многострочную строку с пробелами, поэтому вы можете просто представить, сколько аргументов существует ...: D

Посмотрите, что, когда и зачем основы.

Полезность расщепления слов

Существуют случаи, когда разбиение слов может быть полезным:

Заполнение массива:

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

Это заполнит arr всеми численными значениями, найденными в файле

Циклическое выделение пробелов:

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

Выход:

W: foo
W: bar
W: baz

Передача разделенных пробелов параметров, которые не содержат пробелов:

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

или же

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

Это установит пакеты. Если вы удвоите кавычки $packs то это вызовет ошибку.

Unquoetd $packs отправляет все имена разделяемых пространств в качестве аргументов apt-get , в то время как цитирование будет отправлять строку $packs как один аргумент, а затем apt-get попытается установить пакет с именем apache2 php php-mbstring php-mysql (для первого), который, очевидно, не существует

Посмотрите, что, когда и зачем основы.

Разделение по разделительным изменениям

Мы можем просто выполнить простую замену разделителей из пространства на новую, как показано ниже.

echo $sentence | tr " " "\n"

Он разделит значение sentence переменной и покажет его по строке соответственно.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow