Grep

如何匹配手動概要中特定形式的可選序列,包括變體?

  • June 19, 2014

這個問答中,有一個參考手冊頁概要“鬆散地”基於元語法符號的擴展巴科斯-瑙爾形式。這很有趣,可以作為背景。話雖如此,使用相關術語,您會在手冊的命令概要中找到最常見的元素類型之一是可選序列;由包含在start-option-symbolend-option-symbol之間的**定義列表組成。總而言之,我們經常將其與類似的東西聯繫起來,例如,可以是單個破折號或更長的雙破折號形式,後跟一個或多個字元,例如 in 。[ option ]``ps --help


所以我想匹配我們經常在手冊中看到的一個常見的可選序列模式,它確實:

  • 開始[和結束於]
  • 包含形式-option或的可選序列--option
  • 不一定在括號內居中,即[-a], [ -ab],[-abc ]全部匹配
  • 允許包含選項及其可選元素/說明符的列表,即[-a foo -b bar -c=biz end]
  • 允許其他括號出現在外部括號內,即[--a [-b[-c]] -d foo](將匹配此處的整個輸入)

…但不允許

  • ---任何情況下的三個破折號
  • 更清楚地說,像[option](no dash) 和[], [-], [--]or[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為測試提供一個很好的可選序列變體。

您可以(使用 GNU grep):

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

在您的問題文本中給出:

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

這個想法是使用 PCRE 及其遞歸匹配運算符,如pcrepattern(3)匹配嵌套中所述[...]

引用自:https://unix.stackexchange.com/questions/138109