Переменная без кавычек (как в $var) или подстановка команд (как в $(cmd)или `cmd`) - это оператор split + glob в оболочках типа Борна.
То есть их содержимое разделяется в соответствии с текущим значением $IFSспециальной переменной (которая по умолчанию содержит пробел, символы табуляции и символы новой строки)
И затем каждое слово, полученное в результате этого разделения, подвергается генерации имени файла (также известной как глобализация или расширение имени файла ), то есть они рассматриваются как шаблоны и расширяются до списка файлов, которые соответствуют этому шаблону.
Таким for i in $(xrandr)образом $(xrandr), поскольку он не находится в кавычках, он разбит на последовательности символов пробела, табуляции и новой строки. И каждое слово, полученное в результате этого разбиения, проверяется на совпадение имен файлов (или оставляется как есть, если они не совпадают ни с одним файлом) и forпроходит по всем.
В for i in "$(xrandr)", мы не используем оператор split + glob, так как подстановка команды заключена в кавычки, поэтому в цикле есть одно проходное значение для одного значения: выход xrandr(без завершающих символов новой строки, которые заменяет подстановка команды ).
Однако в echo $i, $iснова не заключаются в кавычки, поэтому снова содержимое $iразделяется и подвергается генерации имени файла, и они передаются echoкоманде как отдельные аргументы (и echoвыводят ее аргументы через пробелы).
Итак, урок усвоен:
- если вы не хотите разбивать слова или генерировать имена файлов , всегда заключайте в кавычки расширения переменных и подстановки команд
- если вы хотите разделить слова или создать имя файла , оставьте их без кавычек, но установите их
$IFSсоответствующим образом и / или включите или отключите создание имени файла, если необходимо ( set -f, set +f).
Как правило, в приведенном выше примере, если вы хотите перебрать пустой разделенный список слов в выходных данных xrandr, вам необходимо:
- оставить значение
$IFSпо умолчанию (или сбросить его) для разделения на пробелы
- Используйте,
set -fчтобы отключить генерацию имени файла, если вы не уверены, что xrandrникогда не выводите символы *или ?или [(которые являются подстановочными знаками, используемыми в шаблонах генерации имени файла)
И только затем используйте оператор split + glob (оставьте подстановку команды или расширение переменной без кавычек) в inчасти forцикла:
set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done
Если вы хотите , чтобы цикл по (непустым) линиям в xrandrвыходе, вы должны установить $IFSна символ новой строки:
IFS='
'