Котирується проти без котирування розширення рядків


11
  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

Я розумію, чому 1 відрізняється від 2. Але чому 3 дає інший вихід від 2? Будь-ласка, поясніть результат. Як цитати працюють на нових рядках?



Відповіді:


19

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

4

Цитується новий рядок - це новий рядок. Таким чином, echo "$1"наводиться єдиний аргумент командного рядка на відлуння, який потім друкує нові рядки безпосередньо.

Новим рядком без котирування є пробіл. Так echo $1дає багато аргументів командного рядка відлуння, яке друкує їх один за одним, розділених пробілами.


Новий рядок, який не котирується, пробіл - це занадто велика кількість скорочень, щоб бути дійсно корисним як пояснення поведінки ІМО.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.