Вы можете сохранить и присвоить IFS по мере необходимости. В этом нет ничего плохого. Нередко сохраняют его значение для восстановления после временной, оперативной модификации, как в примере с присваиванием массива.
Как упоминает @llua в своем комментарии к вашему вопросу, простое отключение IFS восстановит поведение по умолчанию, эквивалентное назначению пробела-табуляции-новой строки.
Стоит подумать о том, как может быть более проблематично не устанавливать / не устанавливать IFS явно, чем делать это.
Из версии POSIX 2013, 2.5.3 Переменные оболочки :
Реализации могут игнорировать значение IFS в среде или отсутствие IFS в среде во время вызова оболочки, и в этом случае оболочка должна установить IFS на <space> <tab> <newline>, когда она вызывается ,
Вызванная POSIX-совместимая оболочка может наследовать или не наследовать IFS из своего окружения. Из этого следует:
- Переносимый сценарий не может надежно наследовать IFS через среду.
- Сценарий, который намеревается использовать только поведение разделения по умолчанию (или присоединение, в случае
"$*"
), но который может выполняться под оболочкой, которая инициализирует IFS из среды, должен явно установить / сбросить IFS, чтобы защитить себя от вторжения в окружающую среду.
NB. Важно понимать, что для этого обсуждения слово «вызванный» имеет особое значение. Оболочка вызывается только тогда, когда она вызывается явно, используя свое имя (включая #!/path/to/shell
шебанг). Подоболочка - например, которая может быть создана $(...)
или cmd1 || cmd2 &
- не является вызванной оболочкой, и ее IFS (вместе с большей частью среды выполнения) идентичен родительскому. Вызванная оболочка устанавливает значение $
pid, в то время как подоболочки наследуют его.
Это не просто педантичное разоблачение; в этой области существует фактическое расхождение. Вот краткий скрипт, который тестирует сценарий с использованием нескольких различных оболочек. Он экспортирует измененный IFS (установленный в :
) в вызванную оболочку, которая затем печатает свой IFS по умолчанию.
$ cat export-IFS.sh
export IFS=:
for sh in bash ksh93 mksh dash busybox:sh; do
printf '\n%s\n' "$sh"
$sh -c 'printf %s "$IFS"' | hexdump -C
done
IFS обычно не помечен для экспорта, но, если это так, обратите внимание, как bash, ksh93 и mksh игнорируют окружение IFS=:
, в то время как dash и busybox это соблюдают.
$ sh export-IFS.sh
bash
00000000 20 09 0a | ..|
00000003
ksh93
00000000 20 09 0a | ..|
00000003
mksh
00000000 20 09 0a | ..|
00000003
dash
00000000 3a |:|
00000001
busybox:sh
00000000 3a |:|
00000001
Некоторая информация о версии:
bash: GNU bash, version 4.3.11(1)-release
ksh93: sh (AT&T Research) 93u+ 2012-08-01
mksh: KSH_VERSION='@(#)MIRBSD KSH R46 2013/05/02'
dash: 0.5.7
busybox: BusyBox v1.21.1
Хотя bash, ksh93 и mksh не инициализируют IFS из среды, они реэкспортируют свои модифицированные IFS.
Если по какой-либо причине вам нужно переносить IFS через среду, вы не можете сделать это, используя сам IFS; вам нужно будет присвоить значение другой переменной и пометить эту переменную для экспорта. Затем дети должны будут явно присвоить это значение своим IFS.