$ ins_data="3,998 of 5,903"
$ IFS=' of ' read -ra ins_data_arr <<< ${ins_data}
$ declare -p ins_data_arr
declare -a ins_data_arr='([0]="3,998" [1]="" [2]="5,903")'
$ IFS=' of ' read -ra ins_data_arr <<< "$ins_data"
$ declare -p ins_data_arr
declare -a ins_data_arr='([0]="3,998" [1]="" [2]="5,903")'
Сначала я обнаружил, что такое поведение довольно запутанно: откуда взялась эта пустая область? Я думал, что любая последовательность символов IFS будет разделять поля.
Это верно для значения по умолчанию IFS .
Это очень тонкое поведение IFS, связанное с Разделение слов :
Если IFS
имеет значение, отличное от значения по умолчанию, то последовательности символов пробела space
, tab
и newline
игнорируются в начале и конце слова, пока символ пробела находится в значении IFS
(символ пробела IFS
). Любой символ в IFS
, который не является IFS
пробелом, наряду с любыми соседними IFS
пробелами, разделяет поле. Последовательность из IFS
пробельных символов также рассматривается как разделитель.
Таким образом: последовательности из ноля или более пробелов и одиночных непробельных полей символов IFS.
Пустой элемент массива с индексом 1 - это пустая строка между «o» и «f».
Этот тест подтверждает это утверждение:
$ IFS=' of ' read -ra ins_data_arr <<< "3,998 off 5,903"
$ declare -p ins_data_arr
declare -a ins_data_arr='([0]="3,998" [1]="" [2]="" [3]="5,903")'
Теперь у нас есть пустое поле между "o" и "f" и пустое поле между "f" и "f".
Я предполагаю, что это новое поведение для bash версии 4 - по умолчанию bash на OSX имеет версию 3. что-то. Ответ на изменение поведения будет где-то здесь: https://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=bash-4.4
Нашел: https://git.savannah.gnu.org/cgit/bash.git/tree/CHANGES?h=bash-4.4#n3970
ZZ. Код разделения слов теперь обрабатывает символ IFS, который не является пробелом,
табуляция или перевод строки и любые соседние пробелы IFS в виде одного разделителя, как
SUSv3 / XPG6 требуют.
Этот документ "изменения между этой версией, bash-3.1-alpha1,
и предыдущая версия, bash-3.0-release. "- так что ваша версия" она работает "bash должна быть очень старой.
Сказав все это, я рекомендую исправить: не используйте пользовательский IFS, просто учтите тот факт, что вы прочтете 3 слова:
$ read -r missed of total <<<"$ins_data"
$ declare -p missed of total
declare -- missed="3,998"
declare -- of="of"
declare -- total="5,903"
$ echo "${missed//,/}"
3998
$ echo "${total//,/}"
5903