Деякі випадки, коли кількість пробілів має значення в сценаріях bash (або інших оболонках)


14

Мені сказали, що пробіли важливі в bashінших сценаріях оболонок, і я не повинен змінювати існування пробілів, якщо я не знаю, що я роблю. Під «зміною існування» я маю в виду або вставити пробіл між двома символів без пробілів або видалення пробілу між двома символів без пробілів, наприклад , зміна var="$val"в var ="$val"або навпаки. Я хочу спитати

Чи є випадки, коли використання одного простору або використання декількох послідовних пробілів у скрипті оболонки має значення? .

(Звичайно, вставка / видалення пробілу в лапках має значення, як перехід echo "a b"на echo "a b"або навпаки. Я шукаю інші приклади, крім цього тривіального прикладу.)

Я наштовхнувся на це питання, але це стосується додавання та видалення пробілів між двома символами, які не є пробілами, для яких я знаю безліч прикладів, які можуть змінити значення.

Будь-яка допомога буде вдячна. По можливості включайте більше різновидів мушлі.

Відповіді:


19

Поза цитатами оболонка використовує пробіл (пробіли, вкладки, новий рядок, повернення каретки тощо) як роздільник слова / лексеми. Це означає:

  • Речі, не розділені пробілом, вважаються одним "словом".
  • Речі, розділені одним або кількома символами пробілу, вважаються двома (або більше) словами.

Дійсна кількість символів пробілу між кожною "річчю" не має значення, якщо існує хоча б одна.


Дякую. Я не можу знайти жодного зустрічного прикладу. Я просто хочу переконатися.
Вейджун Чжоу

2
Bash також вважає канали форми та вертикальні вкладки пробілом.
fpmurphy

правда. Я спочатку написав "... нові рядки тощо", а потім змінив його, щоб явно додати повернення перевезення. випадково скинув "тощо".
cas

Що робити, якщо кількість пробілів настільки велика, що програма не може вписатися в пам'ять?
Worse_Username

7
@Worse_Username Пробіл не повинен вміщуватися в пам'яті. Я щойно створив 48 Гб сценарій на машині з 8 ГБ оперативної пам’яті та 20 Гб свопу. Це пройшло просто чудово. Щоб прорізати всю цю пробілну пройшло 3 хвилини, але врешті-решт він успішно запустив echoкоманду з стільки пробілів між командою та аргументом.
kasperd

23

Це, мабуть, обман, але це:

rm foo\ bar         # "delete the file named 'foo bar'"

відрізняється від цього:

rm foo\  bar        # "delete the files named 'foo ' and 'bar'"

навіть якщо пробіли не в лапках. ;-)

Більш бентежно це:

rm \
    foo          # "delete the file named 'foo'"

відрізняється від цього:

rm \ 
    foo          # "delete the file named ' ', then run the command 'foo'"

навіть якщо вони виглядають однаково!


Незважаючи на те, що пробіли не містяться в лапках, зворотна косої риски функціонально схожа на форму цитування, і я би ставлю це до тієї ж категорії, що і "тривіальний приклад" питання. (Цікаво, хоча.)
David Z

12

Якщо ми не будемо говорити про космічному характер ( U+0020), але будь-який символ пробілу ( U+0020, \n, \tі т.д.), то один конкретний випадок приходить мені на розум: ось-документи.

Цей код (з використанням пробілів):

cat <<- 'EOF'
<space><space>foo
EOF

Буде надруковано:

  foo

Але цей код (використовуючи вкладки):

cat <<- 'EOF'
<tab><tab>foo
EOF

Буде надруковано:

foo

Це тому, що ( як заявляється POSIX ):

Якщо оператор перенаправлення є <<-, всі провідні <tab> символи повинні бути позбавлені від вхідних ліній та рядка, що містить кінцевий роздільник.


1
Це цікаво. Я подумав тут-документи, але не знав <<-оператора. Велике спасибі.
Вейджун Чжоу

тут документи - це форма цитованого тексту, а не код оболонки. розділення слів на оболонки не застосовується.
cas

2

Це також має ефект при написанні заяв про призначення. Начебто, якщо я скажу, що FOO=xyzце створить змінну середовища, названу FOOзі значенням xyz, але якщо я відокремлюю рівний пробіл, він подумає, що я викликаю програму з ім'ям FOOarg =xyz. Тож має значення, коли мова йде про певний синтаксис.


Зазвичай FOO=xyzстворює внутрішню змінну оболонки, але не змінну середовища. Вам потрібно set -aабо export FOO=xyzдля цього (тобто зробити його частиною оточення позапрограшних підпроцесів).
Hauke ​​Laging

0

Я натрапив на хороший приклад «простору» і подумав поділитися тут. Наступна умова не відповідає справжньому тому, що я знаходився десь від 100 до 1000.

if [ $i -ge 100 -a $i -lt 1000]; then  <some code here>  fi

Зауважте пропущений пробіл між 1000 та квадратною дужкою, що закривається

Але коли вона буде змінена, як зазначено нижче, вона працює як очікувалося.

>  if [ $i -ge 100 -a $i -lt 1000 ]; then  <some code here>  fi

Так, перехід від простору до одного або декількох просторів очевидно має значення, наприклад, наприклад, відповідь каса вище. Тест [ ... ] є регулярною командою , так що це в принципі так само , як cp foo barпроти прогнозу cp foobar.
ilkkachu

@ilkkachu Щоправда, але це не так інтуїтивно у випадку, про який я згадував, і що згадується для cp foo bar проти cp foobar
Maneesh
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.