Bash строка в массив с IFS
У меня возникли проблемы с использованием IFS для преобразования моей строки в массив. Вот что я имею в качестве строки:
"Jun01 Jun02 Jun03 Jun04 Jun05 ..." #in that format, separated by spaces
И вот код, который я пробовал:
IFS=" " #set it to space character
DATES_ARRAY=($DATES_STRING) #from above
echo ${DATES_ARRAY[0]} #output is empty
Однако, когда я удаляю строку IFS, она работает. Но я использовал несколько строк, чтобы распечатать его значение по умолчанию ASCII, и я получил "32", что означает "пробел". Будучи программистом OCD, я хотел бы сам настроить его, чтобы быть в безопасности... Я не знаю, как это будет предустановлено априори!
Итак, почему попытка установить IFS в Space вручную не работает?
Ответы
Ответ 1
Это действительно работает, но в любом случае это необязательно, потому что по умолчанию гарантируется, что пространство будет в IFS. Не устанавливайте его вручную. Это может вызвать проблемы.
В принципе, никогда не используйте разбиение слов в Bash. Иногда это требовало укусить пулю и использовать ее, если она ограничена POSIX sh, если ее использовать очень осторожно. Если вы собираетесь установить IFS, установите его в среде одной из немногих команд, где он имеет некоторый эффект или, самое большее, локально для функции.
Вам никогда не понадобится использовать это, поэтому я не буду все объяснять:
$ printf -v str '%s ' Jun{01..10}
$ set -f
$ IFS=' ' declare -a 'arr=($str)'
$ declare -p arr
declare -a arr='([0]="Jun01" [1]="Jun02" [2]="Jun03" [3]="Jun04" [4]="Jun05" [5]="Jun06" [6]="Jun07" [7]="Jun08" [8]="Jun09" [9]="Jun10")'
IFS установлен в пространство здесь избыточно, чтобы показать, что он работает.
Вероятно, самый правильный способ перейти от строки к массиву - использовать read
. Много примеров здесь.
Каннонический метод:
read -ra arr <<<"$str"
где IFS необязательно устанавливается в среде read
, чтобы действовать как разделитель, если это нечто иное, чем пробелы.
Ответ 2
Я предлагаю не использовать $IFS
самостоятельно для разделения слов в массив, поскольку установка и возврат $IFS - это боль. Используйте что-то вроде этого:
DATES_STRING='Jun01 Jun02 Jun03 Jun04 Jun05'
IFS=' ' read -a DATES_ARRAY <<< "$DATES_STRING"
Я также предлагаю явно установить $IFS
в среде read
, чтобы вы были абсолютно уверены, что это такое.
Ответ 3
По умолчанию $IFS
следует использовать пробел в качестве разделителя маркеров, включая вкладки и символы новой строки.
Попробуйте следующее:
echo "$IFS" | cat -vte
Если вы не изменили $IFS
, вывод должен быть:
^I$
$
Это пробел, за которым следует одна вкладка: ^I
и новая строка - обратите внимание, что cat
печатает любые символы новой строки как $
.
И поэтому ваш отрывок script должен работать, не касаясь $IFS
.