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