Использование внутреннего разделителя полей при захвате данных массива из команды в скрипте bash

Когда я запускаю команду

git cherry origin/Server_Dev

в моем репозитории git я получаю список коммитов вида

+ 95b117c39869a810595f1e169c64e728d2d7443d
+ e126f1b996ecf1d2a8cf744c74daa92cce338123
+ 869169a6cb0bbe8f1922838798580a1e74ec3884
+ 667819b617c88bd886dc2001f612b5c7a4d396c3
+ fd41328a84b0a127affa6fe4328c93e933de378c
+ cfe1807e5d4acc6b5e75f4463dadb3b1c957376f

Это хорошая вещь.

Теперь я хочу выполнить эту команду из скрипта bash и записать вывод в массив, используя следующий код:

commit_hashes=(`git cherry origin/Dev`)
echo ${commit_hashes[@]}

который дает следующий вывод:

+ 95b117c39869a810595f1e169c64e728d2d7443d + e126f1b996ecf1d2a8cf744c74daa92cce338123 + 869169a6cb0bbe8f1922838798580a1e74ec3884 + 667819b617c88bd886dc2001f612b5c7a4d396c3 + fd41328a84b0a127affa6fe432
8c93e933de378c + cfe1807e5d4acc6b5e75f4463dadb3b1c957376f

Это не хорошая вещь

Мой список коммитов возвращается в виде строки, которую я должен сначала разбить, прежде чем использовать. После некоторых поисков я обнаружил, что если я добавлю IFS="" в моем сценарии до сбора данных, мои проблемы будут решены.

Поэтому я отредактировал свой код для чтения

IFS=""
commit_hashes=(`git cherry origin/Dev`)
echo ${commit_hashes[@]}

какой выход

+ 95b117c39869a810595f1e169c64e728d2d7443d
+ e126f1b996ecf1d2a8cf744c74daa92cce338123
+ 869169a6cb0bbe8f1922838798580a1e74ec3884
+ 667819b617c88bd886dc2001f612b5c7a4d396c3
+ fd41328a84b0a127affa6fe4328c93e933de378c
+ cfe1807e5d4acc6b5e75f4463dadb3b1c957376f

Это полностью положило конец моему чувству реальности.

Мне нравится знать, почему вещи делают то, что они делают, поэтому после еще нескольких поисков я обнаружил, что это называется Internal Field Separator и он используется в системах Unix интерпретаторами команд для определения, где разбивать шаблоны на токены.

Это я понимаю

Что я не понимаю, так это

  1. Почему установка этой переменной в пустую строку позволила ей обрабатывать данные моего массива в здравом смысле.
  2. Почему я должен был установить это в первую очередь, вместо того, чтобы интерпретатор осознавал, что он имеет дело с данными массива и обрабатывает их соответствующим образом.
  3. Какой эффект при установке Внутреннего разделителя полей на пустую строку будет иметь место в общей схеме вещей, поскольку по умолчанию он содержит символы для пробела, табуляции и новой строки.

Была бы признательна за помощь в обдумывании этих трех пунктов.

1 ответ

Решение

Смотри man bash / Arrays. Все хорошо с вашим массивом. Когда вы делаете

echo ${commit_hashes[@]}

echo показывает все элементы массива в одной строке, как сказано. Когда ты сказал

for i in `seq 10`; do
    echo ${commit_hashes[$i]}
done

вы увидите, что отображается только одна запись в строке.

Когда вы установите IFS= в пустую строку, однако, результат git cherry не разбивается на несколько значений. Вся строка, включая символы новой строки, присваивается первому элементу массива. если ты

echo ${commit_hashes[0]}

во втором случае вы увидите, что эхо показывает все выходные строки.

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