Как сопоставить определенную форму необязательной последовательности из ручного синопсиса, включая вариации?

Как сопоставить определенную форму необязательной последовательности из ручного синопсиса, включая вариации?

ВэтотВопрос и ответ есть ссылка на то, что краткие описания страниц руководства основаны «в общих чертах» наРасширенная форма Бэкуса–Наураметасинтаксической нотации. Это интересно и служит фоном. При этом, используя связанную терминологию, один из наиболее распространенных типов элементов, которые вы найдете в синопсисе команды из руководства, этонеобязательная последовательность; сделан изопределения-списокзаключенный междустарт-опция-символиконечный-опцион-символ. Во многих словах то, что мы часто ассоциируем с подобными словами [ option ], например, может быть одинарным тире или более длинной формой двойного тире, следующей за одним или несколькими символами, например, в ps --help.


Поэтому я хотел бы сопоставить распространенный шаблон необязательной последовательности, который мы часто видим в руководствах, который на самом деле:

  • Начинается с [и заканчивается]
  • Содержит необязательную последовательность вформаили-option--option
  • Не обязательно центрируется внутри скобок [-a], [ -ab]т.е. [-abc ]все соответствует
  • Позволяет создать список, содержащий опцию и ее необязательный элемент/спецификатор, т.е.[-a foo -b bar -c=biz end]
  • Позволяет другим скобкам появляться внутри внешних скобок, т.е. [--a [-b[-c]] -d foo](будет соответствовать всему вводу здесь)

... ноне делаетпозволять:

  • Три тире ---при любых обстоятельствах
  • Чтобы было яснее, такие вещи, как [option](без тире) и [], [-], [--]или [foo-bar=a]по отдельности не должны совпадать.

Данные не содержат слишком много необычных случаев, таких как примеры, представленные выше (я не знаю, как это сделать).иметь делос непарными скобками тоже, но это выходит за рамки этого). Попытка удовлетворить требования, grepкак я это сделал, возможно, была не лучшей идеей, оглядываясь назад, но я попробовал:

grep -E '\[{1,}([[:space:]]{0,}[[:punct:]]{0,}[[:alnum:]]{0,}){0,}(-{1,2}[[:alpha:]]{1,}){1,}([[:alnum:]]{0,}[[:punct:]]{0,}[[:space:]]{0,}){0,}\]{1,}'

Он сопоставляет некоторые шаблоны 1 , в соответствии с тем, что я хочу, но у него есть недостатки, его трудно контролировать и использовать повторно. Использование произвольных наборов(3) скобок для группировки элементов с целью управления совпадающими повторениями для создания "блоков" также не помогает в этом отношении (но помогает при отладке). Игра с классами символов для обслуживания ввода кажется совершенно непредсказуемой.

Так как же это сделать, используя лучшее выражение и/или другой инструмент/подход? Как вы справляетесь с такими длинными регулярными выражениями, если используете их — в этом случае вам придется использовать команду много раз, чтобы отфильтровать содержимое? Нужно ли мне заранее по-другому манипулировать содержимым, чтобы помочь мне с этим?


1.выходот итерации по файлам manpages дает хорошую возможность для тестирования. С grep здесь я использовал: for i in /usr/share/man/man1/*.gz; do basename "${i//.1.gz}"; my_grep_command_above <<< "$(man -l "$i")"; doneиспользуя весь вывод manpages. В противном случае man manили man asпредоставляет хорошую вариацию дополнительных последовательностей для тестирования.

решение1

Вы можете сделать (с GNU grep):

grep -Po '\[\s*--?(?!-)((?>[^][]+)|\[(?1)*\])+\]'

Что по тексту вашего вопроса дает:

[-a]
[ -ab]
[-abc ]
[-a foo -b bar -c=biz end]
[--a [-b[-c]] -d foo]

Идея состоит в том, чтобы использовать PCRE и его рекурсивные операторы сопоставления, как описано в разделе « pcrepattern(3)Сопоставление вложенных объектов» [...].

Связанный контент