bash: IFS "завис" после временного изменения его для построения массива - PullRequest
0 голосов
/ 12 июля 2020

Я столкнулся со странной проблемой после временного изменения IFS с целью построения массива:

$ echo "1 2 3" |while read myVar1 myVar2; do echo "myVar1: ${myVar1}"; echo "myVar2: ${myVar2}"; done
myVar1: 1
myVar2: 2 3
$ IFS=':' myPaths=( ${PATH} )  # this works: I have /home/morgwai/bin on ${myPaths[0]} , /usr/local/sbin on ${myPaths[1]} and so on
$ echo "1 2 3" |while read myVar1 myVar2; do echo "myVar1: ${myVar1}"; echo "myVar2: ${myVar2}"; done
myVar1: 1 2 3
myVar2: 
$ echo $IFS

$ echo "1:2:3" |while read myVar1 myVar2; do echo "myVar1: ${myVar1}"; echo "myVar2: ${myVar2}"; done ;
myVar1: 1
myVar2: 2:3

Обычно, когда я временно меняю IFS для любой другой команды, кроме построения массива (например, IFS=',' echo whatever) его значение изменяется только во время его выполнения, однако здесь кажется, что IFS навсегда изменилось на двоеточие (хотя echo $IFS этого не показывает, что еще более странно ...) .

Это ошибка или какое-то ожидаемое поведение, которого я не понимаю?
Я использую bash версию 4.4.18, если это важно ...

Примечание: я знаю, что могу построить тот же массив, используя IFS=':' read -a myPaths <<< ${PATH}, а затем IFS обычно возвращается к значению по умолчанию, но дело не в этом: я пытаюсь понять, что на самом деле происходит в приведенном мной примере выше.

Спасибо!

1 Ответ

4 голосов
/ 12 июля 2020

Вы просто устанавливаете переменные, а не устанавливаете переменную с последующим выполнением команды (ie, способ построения массива - это чистое присваивание переменной, а не команда, поэтому оба присваивания становятся постоянными).

Проблема с IFS из :, не отображаемым в echo $IFS, вызвана расширением параметров оболочки и разделением слов.

Учтите:

$ IFS=:
$ echo $IFS

$ echo "$IFS"
:

Когда параметр расширение не цитируется, оно подвергается разделению слов послесловиям. Из руководства :

Оболочка сканирует результаты раскрытия параметров, подстановки команд и арифметических c раскрытий, которые не встречались в двойных кавычках для разделения слов.

и

Оболочка обрабатывает каждый символ $IFS как разделитель и разбивает результаты других расширений на слова, используя эти символы в качестве ограничителей полей. Если IFS не задан или его значение равно <space><tab><newline>, значение по умолчанию, то последовательности <space>, <tab> и <newline> в начале и конце результатов предыдущих расширений игнорируются, и любая последовательность символов IFS, не стоящих в начале или конце, служит для разделения слов.

Итак, когда IFS является двоеточием, разделение слова, состоящего только из двоеточия, приводит к (одному) пустому слову. Всегда заключайте переменные в кавычки, чтобы избежать подобных неожиданных ошибок.

...