В чем разница между `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и вы когда-нибудь попробуете только отдельные символы, они будут работать одинаково.
Nacht - Восстановить Монику

Ответы:

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некоторые старые версии fishUnix, 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}представляет меньшую проблему.

Kusalananda
источник
Спасибо за разъяснение "Если abd существует, а acd нет, то он будет расширяться только до abd". Я думаю, это то, чего не хватает в моем ответе.
Вейцзюнь Чжоу
9
Другое важное отличие состоит в том a{b,c}d, что в , bи cчасти не должны быть отдельными буквами; например ex{ten,ci}sion. Хотя ex[tenci]sionили что-то будет соответствовать только одной из этих букв.
Алексис
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. Вот соответствующая часть из Баш руководства (выделено мной):

Разбивка скобок - это механизм, с помощью которого можно генерировать произвольные строки . Этот механизм похож на расширение имени файла (см. Расширение имени файла), но генерируемые имена файлов не должны существовать . Шаблоны, которые должны быть развернуты в фигурные скобки, принимают форму необязательной преамбулы, за которой следует либо последовательность строк, разделенных запятыми, либо выражение последовательности между парой фигурных скобок, за которым следует дополнительный постскриптум. Преамбула имеет префикс к каждой строке, содержащейся в фигурных скобках, а затем к каждой результирующей строке добавляется постскриптум, расширяющийся слева направо.

Согласно комментарию @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}будет работать в bash иначе, чем любая другая оболочка.
Мосви
Спасибо. Я обновлю ответ.
Вейцзюнь Чжоу