Фрагмент вопроса:
IFS=$'\n' a=($str)
интерпретируется как два отдельных назначения глобальных переменных, вычисляемых слева направо, и эквивалентно:
IFS=$'\n'; a=($str)
или
IFS=$'\n'
a=($str)
Это объясняет, почему глобальный IFS
был изменен, и почему слово -разбиение $str
на элементы массива было выполнено с использованием нового значения IFS
.
У вас может возникнуть соблазн использовать подоболочку, чтобы ограничить эффект IFS
модификации, подобной этой:
str="value 0:value 1"
a=( old values )
( # Following code runs in a subshell
IFS=":"
a=($str)
printf 'Subshell IFS: %q\n' "${IFS}"
echo "Subshell: a[0]='${a[0]}' a[1]='${a[1]}'"
)
printf 'Parent IFS: %q\n' "${IFS}"
echo "Parent: a[0]='${a[0]}' a[1]='${a[1]}'"
, но вы быстро заметите, что модификация a
также ограничена подоболочкой :
.
Subshell IFS: :
Subshell: a[0]='value 0' a[1]='value 1'
Parent IFS: $' \t\n'
Parent: a[0]='old' a[1]='values'
Затем у вас может возникнуть соблазн сохранить/восстановить IFS, используя решение из этого предыдущего ответа от @msw или попробовать использовать local IFS
внутри функции , как было предложено от @helpermethod. Но довольно скоро вы замечаете, что у вас возникают всевозможные проблемы, особенно если вы являетесь автором библиотеки, которому необходимо быть устойчивым к неправильному вызову скриптов :
.
IFS
изначально не было установлено? set -u
(a.k.aset -o nounset
)? IFS
читается -только через declare -r IFS
? trap
обработчик `)? Не сохраняйте и не восстанавливайте IFS. Вместо,придерживаться временных модификаций:
Чтобы ограничить изменение переменной одной командой, встроенной -или вызовом функции, используйте IFS="value" command
.
Чтобы прочитать несколько переменных путем разделения по определенному символу (:
, используемому ниже в качестве примера ), используйте:
IFS=":" read -r var1 var2 <<< "$str"
Для чтения массива используйте (вместоarray_var=( $str )
):
IFS=":" read -r -a array_var <<< "$str"
Ограничьте последствия изменения переменной подоболочкой.
Для вывода элементов массива через запятую:
(IFS=","; echo "${array[*]}")
Чтобы записать это в строку:
csv="$(IFS=","; echo "${array[*]}")"
find path -type f -iname "*.gz" -exec zgrep "word" {} \; >>result
Проверено, работает нормально