Чим відрізняється `a [bc] d` (дужки) і` a {b, c} d` (дужки)?


28

У чому різниця між a[bc]dі a{b,c}d? Чому люди використовують, a{b,c}dколи вже є a[bc]d?


Хто сказав вам використовувати command a[bc]d?
Jesse_b

3
Він, безумовно, має своє використання, якщо хтось правильно його розуміє.
Вейджун Чжоу

7
Я думаю, я просто не розумію, як сталася плутанина між ними.
Jesse_b

Мене явно просив цей колег, менш знайомий з Linux, але не останнім часом.
Вейджун Чжоу

@Jesse_b Якщо ви коли-небудь пробуєте їх з операціями над такими файлами, як lsі ви намагаєтеся лише один раз, вони можуть працювати однаково.
Нахт - Відновіть Моніку

Відповіді:


43

Два цілком різні.

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}це менше проблеми.


Дякуємо вам за уточнення "Якщо abd існує, але acd цього немає, він би розширився лише до abd". Я думаю, саме цього не вистачає в моїй відповіді.
Вейджун Чжоу

9
Ще одна важлива відмінність полягає в тому, що в a{b,c}d, bі cчастинах не потрібно бути однієї літери; напр ex{ten,ci}sion. Хоча ex[tenci]sionабо що завгодно буде відповідати лише одному з цих листів.
alexis

7

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}який з’явився лише після bash3.0, а ще більше додано в bash4.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.


2
Розширення дужки - це не «башизм»; вперше він з'явився в Росії csh, задовго до цього bash. Він також присутній у функції бібліотеки glob (3). Різниця полягає в тому, що bashвона виконується перед іншими розширеннями: a=A; ab=A/B; ac=A/C; echo $a{b,c}буде працювати в баші інакше, ніж будь-яка інша оболонка.
mosvy

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