在這問答有一個參考手冊頁概要「鬆散」地基於擴展巴科斯-諾爾範式元語法表示法。它很有趣並且可以作為背景。話雖這麼說,使用相關術語,您在手冊的命令概要中發現的最常見的元素類型之一是可選順序;由一個定義清單封閉在一個之間開始選項符號和結束選項符號。在許多單字中,我們經常將其與類似的東西聯繫起來[ 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)
匹配嵌套中所述[...]
。