正则表达式表示捕获组在一行上的最小出现次数

Regex for minimum number of appearances of capturing group on a line

提问人:raulp 提问时间:10/7/2023 更新时间:10/10/2023 访问量:63

问:

我有一个文本文件,其中每行由一系列数字组成,由空格分隔,后跟一个单词。这些数字仅由数字 1 到 6 组成,每个数字中的数字是有序且唯一的。文件末尾的单词并不重要。

例如:

2356 345 12345 4 4 1 6 gripped
12346 2 2346 123456 2356 56 245 12346 13456 12456 misidentifies
1256 345 24 12456 12356 123456 12356 356 1256 5 26 swine

在我的文件中都是有效的行。

我需要编写一个命令,该命令使用正则表达式来匹配所有包含至少 8 个数字(具有 1 或 6)的行。这意味着该行是匹配的(346、1245、136、23456、1356、123456、123456、123456是 8 个数字),但该行不是匹配项(1、236、145、16、12356 只有 5 个数字)。grep346 1245 136 23456 5 1356 123456 5 123456 123456 octettes1 236 145 23 16 4 12356 4 3 packers

注意:正则表达式不必与整行匹配。grep 返回所有在某处存在匹配项的行,因此唯一重要的部分是至少有 8 个匹配项。

我构造了这个正则表达式:它匹配所有与条件匹配的数字,并且不会123456两次计数。我现在的问题是计算出现次数。如果所有数字匹配一个接一个,{8,} 就足够了,但有时匹配之间有一个(或多个)数字(例如 134、4、245、1245)。((?:(?:123456)|(?:1[2-5]*)|(?:[2-5]*6)) )

我尝试了很多事情,包括将 ,或放在匹配组中重复(使用 {8,}),但似乎没有任何效果。它们要么不匹配,要么产生灾难性的回溯错误。[2-5]{0,5}[2-5]*.*

我对正则表达式很陌生,所以我可能误解了某些事情的工作原理。我知道我需要修改我的捕获组才能使我的 {8,} 量词工作,但我不知道如何操作。

Regex101 链接包含更多示例和我当前的(部分)解决方案

正则表达式 grep

评论


答:

1赞 The fourth bird 10/7/2023 #1

如果只有单个空格,则可以使用

^(?:(?:[2345]+ )*[2345]*[16][1-6]* ){7}(?:[2345]+ )*[2345]*[16]

模式匹配

  • ^字符串的开头
  • (?:非捕获组作为一个整体重复
    • (?:[2345]+ )*(可选)匹配不带 1 或 6 的数字
    • [2345]*[16][1-6]* 将数字与 1 或 6 匹配
  • ){7}关闭非捕获组并重复 7 次
  • (?:[2345]+ )*[2345]*[16]第8场比赛

正则表达式演示

使用 grep 匹配 1 个或多个空格或制表符的示例:-E

grep -E "^(([2345]+[[:blank:]]+)*[2345]*[16][1-6]*[[:blank:]]+){7}([2345]+[[:blank:]]+)*[2345]*[16]" file

使用 grep 匹配 1 个或多个水平空格字符的示例:-P

grep -P "grep -P "^(?>(?:[2345]+\h+)*+[2345]*[16][1-6]*\h+){7}(?:[2345]+\h+)*+[2345]*[16]" file" file
0赞 Cary Swoveland 10/9/2023 #2

您可以将以下正则表达式与:grep

^[ 2-5]*(?:[16][1-6]*[ 2-5]*){8}

演示


请考虑以下字符串。

"34 25 216 5 24   215 16 126 216 356 1 5 26 1 cats"
 0000000111111111112223334444455555667777788

下面标有 () 的子字符串与 .下面标有相同(正)数字序列的每个子字符串都匹配。000000"34 25 2"^[ 2-5]*(?:[16][1-6]*\b[ 2-5]*)


正则表达式包含以下元素:

^          # match the beginning of the string       
[ 2-5]*    # match zero or more charactors in the character class
(?:        # begin a non-capture group
  [16]     # match a character in the character class
  [1-6]*   # match zero or more characters in the character class
  [ 2-5]*  # match zero or more characters in the character class
){8}       # end the non-capture group and execute it eight times

请注意,

(?:[16][1-6]*[ 2-5]*){8}

可以改用,但它效率较低,因为它需要更多的回溯。