Разделение строки при использовании bash не работает на сервере Debian - PullRequest
1 голос
/ 05 марта 2019

Я хочу разбить строку ins_data, используя "of", и получить 2 числа на 2 переменные.

Мой код выглядит так.

#!/usr/bin/env bash

ins_data="3,998 of 5,903"
IFS=' of ' read -ra ins_data_arr <<< ${ins_data}
total_ins=${ins_data_arr[1]//,}
missed_ins=${ins_data_arr[0]//,}

echo $total_ins
echo $missed_ins

Этот код отлично работает на моем компьютере Mac OS.

Но это не работает на сервере Debian.

1 Ответ

1 голос
/ 05 марта 2019
$ 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...