Grep
使用正則表達式匹配重複模式
假設我有一個如下文件
1,2,3-5,6 1,2,3-5,6, 1 1-3 1,2,3-,4,5-7 1,2,3-,4,5-7, 1,2,-3,4,5 1,2,-,3,4 1,2,,,3,4 ,1,2,3
只有以下規則的組合才應被視為有效:
- 範圍
[0-9]+-[0-9]+
- 團體
[0-9]+,[0-9]+
- 單號
[0-9]+
以逗號結尾的行也應該被認為是有效的
我只想提取
1,2,3-5,6 1,2,3-5,6, 1 1-3
由於下面顯示的其他行不符合規則
1,2,3-,4,5-7 1,2,3-,4,5-7, 1,2,-3,4,5 1,2,-,3,4 1,2,,,3,4 ,1,2,3
因為有些行的範圍不完整,所以有些行缺少組中的數字
PS:僅
PCRE
兼容的grep
解決方案會很棒,但也歡迎其他解決方案
與您列出的字元串(以及以 a 開頭的字元串
,
)匹配的完整 pcre 可能是:grep -P '^([0-9]+(-[0-9]+)?(,|$))+$'
我們是怎麼到那裡的?
要匹配的最基本元素是數字,假設
[0-9]
或\d
PCRE 中更簡單的元素是英語 (ASCII) 數字的正確正則表達式。這還不如不是。例如,它可以匹配梵文數字。然後你需要寫:[0123456789]
準確地說。然後,一系列數字將與 匹配
[0-9]+
。在一個數字(1 或 3 或 26)之後,可以是一個破折號“-”,後跟一個或多個數字(又是一個數字):
[0-9]+(-[0-9]+)?
其中
?
dash-number 序列是可選的。然後,每個數字:(
3
或數字範圍:)4-9
後面應該跟一個逗號,
(多次):([0-9]+(-[0-9]+)?,)+
除了最後一個逗號可能會失去:
([0-9]+(-[0-9]+)?(,|$))+
並且,如果需要,可能會出現前導逗號:
(^|,)([0-9]+(-[0-9]+)?(,|$))+
將正則表達式錨定到測試文本的開頭和結尾是一個非常好的主意:
^((^|,)([0-9]+(-[0-9]+)?(,|$))+)$
您可以在本站測試和編輯PCRE 正則表達式
如果應該拒絕前導逗號,請使用:
^(([0-9]+(-[0-9]+)?(,|$))+)$
這沒有給正則表達式機器留下可選的解釋。所有都必須匹配,任何不匹配的都會被拒絕。
它可以寫成(GNU)擴展正則表達式:
grep -E '^(([0-9]+(-[0-9]+)?(,|$))+)$'
作為基本正則表達式 (BRE):
grep '^\(\([0-9]\{1,\}\(-[0-9]\{1,\}\)\{0,1\},\{0,1\}\)\{1,\}\)$'
如果逗號
,
是可選{0,1}
的,正則表達式引擎可能會決定匹配什麼。描述性正則表達式?
一個更具描述性的正則表達式,帶有空格和註釋,可以通過以
(?x)
in開頭pcregrep
pcregrep '(?x) # tell the regex engine to allow # white space and comments. (?(DEFINE) # subroutines that will be used. (?<nrun> [0-9]+) # run of digits (n-run). # define a range pair. A number run followed by # an optional ( dash and another number run ) (?<range> (?&nrun) (-(?&nrun))? ) # range pair. (?<sep> ,) # separator used. ) # end of definitions. # Actual regex to use: # (range) that ends in a (sep) # or is at the end of the line, # several times (+). ^( (?&range) ((?&sep)|$) )+$ ' file
此正則表達式(一旦編譯)與原始正則表達式完全相同,並且執行速度同樣快。當然,編譯正則表達式需要(可以忽略不計的)額外時間。
測試範例在這裡