Змінна без котирування (як in $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='
'