Переменная без кавычек (как в $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='
'