Каким образом разделение строки на массив путем "чтения" с помощью разделителя слов IFS в bash создает дополнительный пробел?

Имея только один символ для IFS, он отлично работает:

shell@kernel: ~> l="2.4.3"; IFS="." read -a la <<< "$l"; for ((i = 0; i < ${#la[@]}; ++i)) do echo ${la[$i]}; done;
2
4
3

Хотя для IFS есть два символа, генерируется дополнительный пробел

shell@kernel: ~> l="2->4->3"; IFS="->" read -a la <<< "$l"; for ((i = 0; i < ${#la[@]}; ++i)) do echo ${la[$i]}; done;
2

4

3
shell@kernel: ~> l="2..4..3"; IFS=".." read -a la <<< "$l"; for ((i = 0; i < ${#la[@]}; ++i)) do echo ${la[$i]}; done;
2

4

3

Как я могу избавиться от лишнего элемента в массиве?

3 ответа

Решение

Продолжая комментарий, вы можете либо проверить наличие пустого элемента перед сохранением значения в массиве, либо иметь дело с пустым значением, когда echo Это. Честно говоря, проще сделать последнее, например,

l="2->4->3"; IFS="->" read -a la <<< "$l"; \
for ((i = 0; i < ${#la[@]}; ++i)) do \
[ -n "${la[i]}" ] && echo ${la[$i]}; done

Выход

2
4
3

Вы можете преобразовать разделитель -> в один символ с:

l="2->4->3"

IFS="-" read -a la <<< "${l//->/-}"

printf '%s' "${la[@]}"

Если есть риск, что строка может содержать дополнительные - затем используйте маловероятный символ, который будет в строке:

IFS="┵" read -a la <<< "${l//->/┵}"

Я бы просто использовал sed для замены разделителя

видите, повторное использование вашего скрипта + sed

bash$ l="2->4->3"
bash$ read -a la <<< "$(echo $l | sed 's/->/ /g')"
bash$ for ((i = 0; i < ${#la[@]}; ++i)) do echo ${la[$i]}; done
2
4
3

но я думаю, что сделал бы это совсем по-другому

bash$ l="2->4->3"
bash$ for x in `echo $l | sed 's/->/ /g'`; do echo $x; done
2
4
3

надеюсь это поможет

Другие вопросы по тегам