изменение $ IFS в групповой команде является наполовину постоянным - PullRequest
1 голос
/ 28 июня 2019

Это использует bash 4.3.48.

$ ARR=(entry1 entry2 entry3)
$ echo "${ARR[*]}"
entry1 entry2 entry3

Вещи работают, как и ожидалось, до тех пор, пока здесь, но после

$ { IFS=: ; echo "${ARR[*]}" ;}
entry1:entry2:entry3

IFS странным образом изменяется наполовину после изменения

$ echo "${ARR[*]}"
entry1:entry2:entry3
$ echo $IFS

$ echo "$IFS"
:

Поскольку я не могу разобраться в этом поведении, я бы предположил, что это ошибка.Там может быть соединение с IFS изменения с Bash 4.2 .

Ответы [ 3 ]

5 голосов
/ 28 июня 2019
$ echo $IFS

$ echo "$IFS"
:

Запись раскрытия переменной без двойных кавычек приводит к разделению слов (и глобализации). Разделение слов разбивает строку на символы $IFS. Когда вы пишете $var, это похоже на скрытый вызов функции split+glob($var).

Если подумать, то написание $IFS без кавычек обречено на провал. Он разбивается на $IFS по символам внутри $IFS. Как мета. Результатом является пустая строка, независимо от того, что $IFS установлено в:

$ (IFS='abc'; echo $IFS)

$ (IFS='<>'; echo $IFS)

$ (IFS='!@#$'; echo $IFS)

Урок: всегда заключайте в кавычки расширения переменных.

$ (IFS='abc'; echo "$IFS")
abc
$ (IFS='<>'; echo "$IFS")
<>
$ (IFS='!@#$'; echo "$IFS")
!@#$
2 голосов
/ 28 июня 2019

{ ... } не работает в подоболочке.Таким образом, все изменения в пределах { .. } видны в текущей оболочке.

{ a=1; }; echo $a

Включая IFS.Вы установили IFS=:, и изменение остается за скобками.

{ IFS=:; }; echo "$IFS"

Теперь мы приступаем к расширению и разбиению слов .Вот почему независимо от того, что для IFS установлено следующее, всегда будет печататься пустая строка:

echo $IFS

IFS - это сам разделитель.Выше echo получает один пустой аргумент.echo $IFS эквивалентно echo ''.Пример: попробуйте, что будет напечатано следующее:

IFS=@; echo Hello${IFS}world

Чтобы напечатать значение IFS, вы должны заключить его в кавычки, в противном случае оно действует как разделитель слов.

Способ печатичлены массива, разделенные первым символом внутри IFS, должны использовать подоболочку ( .. ):

( IFS=:; echo "${arr[*]}"; )
2 голосов
/ 28 июня 2019

{ ... ; } запускает команды в контексте текущей оболочки. $ IFS (или любая другая переменная), измененная внутри фигурных скобок, сохраняет свое значение даже после закрывающей скобки.

Чтобы локализовать изменение переменной, используйте подоболочку (круглые скобки):

(IFS=:; echo "${arr[*]}")

Причина, по которой echo $IFS не выводит двоеточие, другая. Фактически, после того как $ IFS был установлен в :, любая переменная, содержащая :, печатает пусто:

IFS=:
x=:
echo $x  # Nothing!

Это потому, что переменная без двойных кавычек подвергается разбиению по словам, в которой для определения разделителя используется $ IFS.

x=a:b:c
echo $x  # a:b:c
IFS=:
echo $x  # a b c

Во втором случае эхо имеет три параметра. Когда вы echo $IFS, параметр отсутствует, независимо от текущего значения $ IFS.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...