在这问答有一个参考手册页概要“松散”地基于扩展巴科斯-诺尔范式元语法表示法。它很有趣并且可以作为背景。话虽这么说,使用相关术语,您在手册的命令概要中发现的最常见的元素类型之一是可选顺序;由一个定义列表封闭在一个之间开始选项符号和结束选项符号。在很多单词中,我们经常将其与类似的东西联系起来[ 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. 的输出迭代手册页文件提供了一个很好的测试机会。在这里,我使用了 grep:for i in /usr/share/man/man1/*.gz; do basename "${i//.1.gz}"; my_grep_command_above <<< "$(man -l "$i")"; done
使用整个联机帮助页输出。否则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)
匹配嵌套中所述[...]
。