简体   繁体   English

我该如何简化这个正则表达式?

[英]How can I simplify this regex?

Here is a rather complex regex: 这是一个相当复杂的正则表达式:

^\s*(?:\d{2}|\d{2}\s*\d{2}|\d{2}\s*\d{2}\s*\d{2}|\d{2}\s*\d{2}\s*\d{2}\s*\d{2}|\d{2}\s*\d{2}\s*\d{2}\s*\d{2}\s*\d{2})\s*$

Graphically, it becomes: 它以图形方式变为:

正则表达式可视化

How can it be reduced? 如何减少?

I have tried positive lookaheads with no success ( (?=\\d{4})[\\s\\d]+ for example). 我尝试过积极的前瞻但没有成功(例如, (?=\\d{4})[\\s\\d]+ )。

Requirements 要求

The regex: 正则表达式:

  • Allows from one to five pairs of numbers. 允许一到五对数字。
  • Allows zero or more blank characters between pairs of numbers. 在数字对之间允许零个或多个空白字符。

Here is a set of valid inputs the regex must match: https://regex101.com/r/hN0pT4/7 以下是正则表达式必须匹配的一组有效输入: https//regex101.com/r/hN0pT4/7

Example

// OK                  // NOK
12                     123
1234                   12 345
123456                 123 45 45
12345678               1 2 3 4 5
1234567890             12 34 56 78 90 11
12 34
12 3456
12 34 56 78
12 34 567890

EDIT Solution: https://stackoverflow.com/a/36361240/363573 编辑解决方案: https//stackoverflow.com/a/36361240/363573

What about the literal translation of: 字面翻译怎么样:

pairs of numbers (max 5 pairs) with zero or more spaces between 成对的数字(最多5对),其间有零个或多个空格

that is: 那是:

^\s*(\d{2}\s*){1,5}\s*$

You can see a demo here . 你可以在这里看到一个演示。

The shortest/simplest is: 最短/最简单的是:

^ *(\d\d *){1,5}$

Notes: 笔记:

  • \\d\\d (4 chars) is shorter/simpler than \\d{2} (5 chars, with quantifier) \\d\\d (4个字符)比\\d{2}更短/更简单(5个字符,带有量词)
  • space char (1 char) is simpler then \\s (2 chars) space char(1 char)比\\s更简单(2个字符)
  • you don't need the trailing \\s* because any trailing spaces are consumed by the inner expression 你不需要尾随\\s*因为内部表达式使用任何尾随空格

See live demo passing all your posted test cases. 查看通过所有已发布测试用例的实时演示

If you really need to allow other whitespace chars (eg tabs), then use: 如果你真的需要允许其他空格字符(例如制表符),那么使用:

^\s*(\d\d\s*){1,5}$

Here is the best I could produce 这是我能做的最好的

^(\d{2} ?){1,5}$

^\s*(\d{2} *){1,5}\s*$   <--- forgot the whitespaces 0 to n times (edit)

Expl : Expl:

^ : Begin of string ^ :字符串的开头

(\\d{2} ?) : Matches pairs of digits with an optional (\\d{2} ?) :匹配数字对与可选项

{1,5} : The group can be repeated one to five times (5 pairs max) {1,5} :该组可以重复一到五次(最多5对)

$ : End of string $ :字符串结束


Regex101 Regex101

Let's break it down: 让我们分解一下:

  • ^\\s*(?:x)\\s*$ is easy enough: start of the input, any whitespace, group x, any whitespace, end - not much to simplyfy here. ^\\s*(?:x)\\s*$很容易:输入的开始,任何空格,组x,任何空格,结束 - 简直就在这里。
  • now group x: \\d{2}|\\d{2}\\s*\\d{2}|\\d{2}\\s*\\d{2}\\s*\\d{2}|\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}|\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2} 现在组x: \\d{2}|\\d{2}\\s*\\d{2}|\\d{2}\\s*\\d{2}\\s*\\d{2}|\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}|\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}

    If you split it at the pipes (ie "or"-operators) you get this: 如果你在管道(即“或” - 操作员)拆分它,你得到这个:
    • \\d{2}
    • \\d{2}\\s*\\d{2}
    • \\d{2}\\s*\\d{2}\\s*\\d{2}
    • \\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}
    • \\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}\\s*\\d{2}

See a pattern? 看模式? They all start with \\d{2} and each time there is one more \\s*\\d{2} - up to 4 times. 它们都以\\d{2}开头,每次还有一个\\s*\\d{2} - 最多4次。 So this can be simplified to \\d{2}(?:\\s*\\d{2}){0,4} 所以这可以简化为\\d{2}(?:\\s*\\d{2}){0,4}

Putting it together you get ^\\s*(?:\\d{2}(?:\\s*\\d{2}){0,4})\\s*$ 把它放在一起就得到^\\s*(?:\\d{2}(?:\\s*\\d{2}){0,4})\\s*$

You can try this 你可以试试这个

^\s*((?:\d{2}\s*){1,5})$

Explanation as per comment ( Regex Breakdown ) 根据评论解释(正则表达式细分

^ #Starting of string
 \s* #Consume any spaces from starting
 (    #Capturing group to capture the whole string if it matches the below requirements (It is not necessary to use it if you are only matching the string)
   (?:\d{2}\s*){1,5} #Non capturing group to check the pattern
 )
$ #End of string

Regex Demo 正则表达式演示

Here's yet another way: 这是另一种方式:

(\d\s*\d\s*){1,5}

Correctly matches all of the OP's examples: 正确匹配所有OP的例子:

match 12 比赛12
match 1234 比赛1234
match 123456 匹配123456
match 12345678 比赛12345678
match 1234567890 符合1234567890
match 12 34 比赛12 34
match 12 3456 比赛12 3456
match 12 34 56 78 比赛12 34 56 78
match 12 34 567890 比赛12 34 567890
no match 123 没有比赛123
no match 12 345 没有比赛12 345
no match 123 45 45 不匹配123 45 45
no match 1 2 3 4 5 不匹配1 2 3 4 5

In your situation, pattern repeat is required. 在您的情况下,需要重复模式。 You could try: 你可以尝试:

^(\s*\d{2}(?:[^\S\n]*\d{2}){0,4}\s*)$

REGEX 101 DEMO REGEX 101演示

Here is the final solution I have selected: 这是我选择的最终解决方案:

^(?:\s*\d{2}){1,5}$

正则表达式可视化

Thank you all guys ! 谢谢大家!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM