【问题标题】:Regular expression match fails if only whitespace after the - character如果 - 字符后只有空格,则正则表达式匹配失败
【发布时间】:2016-12-01 13:15:23
【问题描述】:

我正在研究模式为的正则表达式:

1.0.0[ - optional description]/1.0.0.0[ - optional description].txt

[ - optional description] 部分当然是可选的。所以一些可能的 VALID 值是

1.0.0/1.0.0.0.txt
1.0.0/1.0.0.0 - xyz.txt
1.0.0 - abc/1.0.0.0 - xyz.txt
1.0.0 - abc/1.0.0.0.txt

为了在模式匹配中更加健壮,我想在“-”字符之前和之后匹配零个或多个空格。所以所有这些也是有效的。

1.0.0 - abc/1.0.0.0 - xyz.txt
1.0.0-abc/1.0.0.0-xyz.txt
1.0.0    -abc/1.0.0.0-     xyz.txt

要进行这种匹配,我有以下正则表达式(Java 代码):

String part1 = "((\\d+.{1}\\d+.{1}\\d+)(\\s*-\\s*(.+))?)";
String part2 = "((\\d+.{1}\\d+.{1}\\d+.{1}\\d+)(\\s*-\\s*(.+))?\\.sql)";
pattern = Pattern.compile(part1+ "/" + part2);

到目前为止,这个正则表达式运行良好。但是在进行单元测试时,我发现了一个我还不能完全弄清楚的案例。用例是如果字符串包含“-”字符被1个或多个空格包围,但“-”字符后没有描述。这看起来像:

1.0.0 - /1.0.0.0.txt
1.0.0- /1.0.0.0-xyz.txt

在这些情况下,我希望模式匹配失败。但是使用我当前的正则表达式匹配成功。我想我想要的是,如果有一个“-”字符被任意数量的空格包围,比如“-”,那么它后面还必须至少有 1 个非空格字符。但我不能完全弄清楚这个正则表达式。

谢谢!

【问题讨论】:

  • * 表示 0 或更多,尝试使用 + 表示 1 或更多
  • @Michael 你的正则表达式很大。请尝试 ([\w\s-./]+)。有用吗??

标签: java regex string


【解决方案1】:

类似的,

^\d+\.\d+\.\d+(?:\s*-\s*\w+)?\/\d+\.\d+\.\d+\.\d+(?:\s*-\s*\w+)?.txt$

或者您可以将\.\d+ 重复组合为

^\d+(?:\.\d+){2}(?:\s*-\s*\w+)?\/\d+(?:\.\d+){3}(?:\s*-\s*\w+)?.txt$

Regex Demo


变化

  • .{1} 当你想重复某件事时,不需要{}。它的隐含

  • (?:\s*-\s*\w+) 匹配零个或多个空格 (\s*) 后跟 -、另一个空格和 \w+ 长度大于 1 的描述

    • 此模式末尾的? 使其成为可选。
    • 在结尾处再次重复相同的模式以匹配第二部分。
  • ^ 将正则表达式锚定在字符串的开头。
  • $ 将正则表达式锚定在字符串的末尾。这两个是必需的,因此字符串中没有其他内容。
  • 除非有必要捕获它们,否则不要使用() 对模式进行分组。这会导致内存浪费。如果您想对模式进行分组但不捕获它们,请使用 (?:..)

【讨论】:

  • 谢谢。这让我非常接近。我不得不稍微修改你的来得到我想要的。主要的修改是改变你的\w+。这将描述限制为只有单词字符,但我想打开描述也有空白字符。所以你的 \w+ 我改为 \\S{1}.* 这是任何单个非空白字符,后跟任何字符。而且我确实想捕获一堆组,所以我添加了捕获组。这就是我最终得到的结果:^((\d+\.\d+\.\d+)(?:\s*-\s*(\S{1}.*))?)\/((\d+\.\d+\.\d+\.\d+)(?:\s*-\s*(\S{1}.*))?.txt)$
  • @MichaelRemijan 很高兴听到它有帮助。 :)
【解决方案2】:

在匹配可选部分的组中,您需要将.+ 替换为\\S+,其中\S 表示任何非空白字符。这会强制可选部分包含非空白字符以匹配模式:

String part1
    = "((\\d+\\.\\d+\\.\\d+)(\\s*-\\s*(\\S+))?)";

String part2
    = "((\\d+\\.\\d+\\.\\d+.{1}\\d+)(\\s*-\\s*(\\S+))?\\.txt)";

还要注意.{1}(与. 相同)匹配任何字符。从示例中,您要匹配一个点,因此应将其替换为\.

【讨论】:

    【解决方案3】:

    类似

    ^\d+\.\d+\.\d+(?:\s*-\s*[^\/\s]+)?\/\d+\.\d+\.\d+\.\d+?(?:\s*-\s*[^.\s]+)?\.\w+$
    

    Check it out here at regex101.

    【讨论】:

      猜你喜欢
      • 2021-05-31
      • 1970-01-01
      • 1970-01-01
      • 2020-08-30
      • 1970-01-01
      • 1970-01-01
      • 2018-01-15
      • 2020-12-19
      • 2011-06-19
      相关资源
      最近更新 更多