У чому різниця між a[bc]d
і a{b,c}d
? Чому люди використовують, a{b,c}d
коли вже є a[bc]d
?
ls
і ви намагаєтеся лише один раз, вони можуть працювати однаково.
У чому різниця між a[bc]d
і a{b,c}d
? Чому люди використовують, a{b,c}d
коли вже є a[bc]d
?
ls
і ви намагаєтеся лише один раз, вони можуть працювати однаково.
Відповіді:
Два цілком різні.
a[bc]d
- це шаблон імені файлу (в інших оболонках, ніж оболонки fish
). Він розшириться до двох імен файлів, abd
і acd
якщо це імена існуючих файлів у поточному каталозі.
[...]
Частина являє собою квадратні дужки вираз , яке відповідає одному символу з перерахованих (або елементи яких об'єднуються , коли діапазони включені). Щоб відповідати шаблону a[bc]d
, символ між рядками a
та d
ім'ям файлу повинен бути або a, b
або a c
.
Якщо abd
існує, але acd
ні, він би розширювався лише до abd
, і навпаки.
Якщо ні abd
, ні acd
існувати, в залежності від оболонки і варіант, це не викличе помилку (оригінал Unix sh
, (t)csh
, zsh
, fish
, bash -O failglob
) і , можливо , вийти з оболонки, або залишити шаблон unexpanded¹ (Bourne-подібні і rc
-як оболонки) або розширюватися нічого ( bash/zsh/yash -o nullglob
, деякі старіші версії fish
, оригінал Unix sh
і (t)csh
якщо в цій же команді є інші відповідні глобуси).
a{b,c}d
- це розширення дужок (у оболонках, які підтримують їх). Він розшириться до двох рядків abd
і acd
.
{...}
Частина являє собою розділені коми набору рядків (в даному прикладі, в деякій оболонці, він також може являти собою діапазон , такі як a..k
або 20..25
або більш просунутих з них , як 00..20..2
і 0..20..2%02d
), а також розширення обчислюється шляхом об'єднання кожного з цих рядків з фланкирующим струни a
і d
. Ці рядки можуть бути довше одного символу, а також можуть бути самими розширеними розширеннями.
Розширення відбувається незалежно від того, відповідають ці рядки існуючим іменам або ні.
Якщо ви створюєте рядки, використовуйте розширення дужок. Якщо ви збігаєте назви файлів, використовуйте шаблон імені файлу.
¹ У цьому конкретному випадку a[bc]d
може статися назва існуючого файлу, тому використання речей, таких як rm -f ./*.[ch]
у цих оболонках , потенційно небезпечно, і rm -f ./*.{c,h}
це менше проблеми.
a{b,c}d
, b
і c
частинах не потрібно бути однієї літери; напр ex{ten,ci}sion
. Хоча ex[tenci]sion
або що завгодно буде відповідати лише одному з цих листів.
a[bc]d
відповідність шаблону та є частиною стандарту POSIX. У POSIX це вводиться як "вираз дужки візерунка". Це задокументовано у розділі 2.13 посібника
Якщо без котирування і поза дужкою вираз, наступні три символи мають особливе значення у специфікації шаблонів:
?
Знак питання - це зразок, який повинен відповідати будь-якому символу.
*Зірочка - це візерунок, який повинен відповідати декільком символам, як описано в "Шаблони, що відповідають кільком символам".
[Відкрита дужка повинна вводити вираз у дужці.
Розділ 2.13.3 також згадує те, що він поводиться інакше, ніж можна було б очікувати для звичайних регулярних виразів, коли він використовується для розширення імені файлів (наголос від мене)
Правила, описані дотепер у "Шаблонах", що відповідають одному символу та патернам, що відповідають декільком символам, кваліфікуються за такими правилами, які застосовуються, коли нотація відповідності шаблону використовується для розширення імені файлу:
Символ косої риси в імені контуру повинен бути чітко узгоджений, використовуючи одну або декілька косої риски в шаблоні; він не повинен відповідати ні зірочкою, ні спеціальними символами знака питання, ні виразом дужки. Штрихи в шаблоні повинні бути ідентифіковані перед виразами дужок; таким чином, коса коса риса не може бути включена у вираз дужки візерунка, який використовується для розширення імені файлу. Якщо після невказаного символу відкритої квадратної дужки буде знайдено символ похилої риси до того, як буде знайдено відповідну закриту квадратну дужку, відкрита дужка має розглядатися як звичайний символ. Наприклад, шаблон
"a[b/c]d"
не відповідає таким іменам шляхів, якabd
абоa/d
. Він відповідає лише доріжці буквальноa[b/c]d
.
a{b,c}d
- це розширення брекетів , це не вказано в специфікації POSIX. Ось відповідна частина посібника з bash (наголос мною):
Розширення дужок - це механізм, за допомогою якого можуть формуватися довільні рядки . Цей механізм схожий на розширення імені файлів (див. Розширення імені файлів), але створені імена файлів не повинні існувати . Шаблони, що підлягають розширенню дужок, мають форму необов'язкової преамбули з наступною послідовністю рядків, розділених комами, або вираженням послідовності між парою дужок, а потім необов'язковий постскрипт. Преамбула встановлюється префіксом до кожного рядка, що міститься в дужках, а післяскрипт додається до кожного результуючого рядка, розширюючи зліва направо.
Згідно з коментарем @mosvy, це вперше з'явилося у, csh
але поведінка в ньому bash
відрізняється від csh
інших оболонок. Цей тип розширень брекетів також присутній у glob(3)
.
Існує ще один тип розширень брекетів, {a..z}
який з’явився лише після bash
3.0, а ще більше додано в bash
4.0.
У оболонці, де увімкнено глобул, виконаному в порожній папці, повертається наступний результат
$ echo a[bc]d
a[bc]d
$ echo a{b,c}d
abd acd
У відповідь на коментар @ Jesse_b, якщо ви знаходитесь в інтерактивній оболонці і обидва застосовні, a[bc]d
це менше проблем із набором тексту. Наприклад grep pattern [ab][12].txt
.
csh
, задовго до цього bash
. Він також присутній у функції бібліотеки glob (3). Різниця полягає в тому, що bash
вона виконується перед іншими розширеннями: a=A; ab=A/B; ac=A/C; echo $a{b,c}
буде працювати в баші інакше, ніж будь-яка інша оболонка.
command a[bc]d
?