Основная проблема здесь заключается в том, что вторая строка, IFS=, sentences1=($sentences)
, устанавливает IFS на «,» навсегда; это означает, что вы получите странное и неожиданное поведение при разборе в оставшейся части скрипта. Обратите внимание, что с чем-то вроде IFS=, read ...
этого не произойдет, потому что назначение IFS рассматривается как применение только к команде read
; но в IFS=, sentences1=($sentences)
нет реальной команды, только назначения, поэтому назначения обрабатываются как применимые ко всей оболочке.
Итак, давайте посмотрим, что происходит в остальной части сценария. sentences2=$sentences
просто копирует sentences
в sentences2
, поэтому for sentence in ${sentences2[@]}
это немного странно. sentences2
не является массивом (просто строка), поэтому бит [@]
ничего не делает, но, поскольку IFS по-прежнему ",", он переводит слово "разбито на слова" в "Hello World" и "Questions" - то есть вы получаете правильный результат, но по неправильной причине.
(Примечание: если бы это был фактический массив, вы бы хотели заключить его в двойные кавычки, как, например, в for sentence in "${sentences2[@]}"
чтобы элементы не разделялись на слова.)
Следующая команда for i in $(seq 1 2)
- это то, с чего начинается настоящая проблема. seq 1 2
печатает «1 [newline] 2 [newline]», конструкция $( )
обрезает завершающий символ новой строки, а затем «1 [newline] 2» получает разделение слов - но так как там нет запятой, это рассматривается как одно слово (которое содержит новую строку). Таким образом, внутренний цикл выполняется только один раз, с i
установленным в «1 [newline] 2».
Следующая строка, echo $i $sentence
, печатает «1 [новая строка] 2», затем пробел, за которым следует содержание sentence
. На первой итерации с sentence
"Hello World" это печатает:
1
2 Hello World
... новая строка в середине делает это похожим на две вещи, которые печатаются, но на самом деле это всего лишь одно echo
которое содержит новую строку.
Итак, две большие рекомендации: во-первых, когда вы меняете IFS, измените его позже. Во-вторых, всегда используйте двойные кавычки для ссылок на переменные, чтобы избежать неожиданного разделения слов (и подстановочных знаков). Вот что я получаю за сценарий:
#!/bin/bash
sentences="Hello World,Questions"
saveIFS="$IFS"
IFS=, sentences1=($sentences)
IFS="$saveIFS" # Set IFS back to normal!
for sentence in "${sentences1[@]}"; do # Note double-quotes, and sentences1 is
an actual array
for i in $(seq 1 2); do # No double-quotes, we *want* seq's output to be spli
t
echo "$i" "$sentence" # Double-quotes for safety
done
done