否定字符组以替换所有其他字符

Negate a character group to replace all other characters

我有以下字符串:

"Thu Dec 31 22:00:00 UYST 2009"

我想替换除小时和分钟之外的所有内容,所以我得到以下结果:

"22:00"

我正在使用这个正则表达式:

(^([0-9][0-9]:[0-9][0-9]))

但是它没有匹配到任何东西。

这将是我的实际代码行:

println("Thu Dec 31 22:00:00 UYST 2009".replace("(^([0-9][0-9]:[0-9][0-9]))".toRegex(),""))

有人可以帮我更正正则表达式吗?

我不确定您使用的是什么语言,但是当您可以直接匹配 hh:mm 格式中的第一个数字时,为什么要使用否定。 假设日期字符串格式始终采用 hh:mm 格式。

此正则表达式片段的第一组应匹配 hh:mm。

https://regex101.com/r/aHdehZ/1

要使用的正则表达式是 (\d\d:\d\d)

你的那个不工作的原因是因为你断言该行在分钟和秒之前开始,但事实并非如此。这可以通过删除断言 (^).

来解决

如果您需要保留断言,还有另一种方法。在大多数语言中,您无法在此处使用可变长度的正向后视,但幸运的是,在 Kotlin 中似乎可以。

积极的回顾基本上只是告诉模式“this 出现在我正在寻找的东西之前”。它由以 ?<= 开头的组表示。在这种情况下,您可以使用 (?<=^[\w ]+) 之类的东西。这将匹配行首和它之后的模式能够匹配的位置之间的所有单词字符或空格。将它附加到您的表达式看起来像 (?<=^[\w ]+)([0-9][0-9]:[0-9][0-9])(请注意,您必须转义 \w 才能使其成为字符串并且不会对此感到生气)。

旁注,Yogesh_D 说 \d\d:\d\d 与您的 [0-9][0-9]:[0-9][0-9] 相同是正确的。使用这个,它看起来更像 (?<=^[\w ]+)\d\d:\d\d.

您可以使用多种解决方案,这里有两个:

val text = """Thu Dec 31 22:00:00 UYST 2009"""
val match = """\b(?:0?[1-9]|1\d|2[0-3]):[0-5]\d\b""".toRegex().find(text)
println(match?.value)
    
val match2 = """\b(\d{1,2}:\d{2}):\d{2}\b""".toRegex().find(text)
println(match2?.groupValues?.getOrNull(1))

Both return 22:00. See regex #1 demo and regex #2 demo.

应根据输入字符串的混乱程度来选择正则表达式复杂度。

详情

  • \b - 单词边界
  • (?:0?[1-9]|1\d|2[0-3]) - 一个可选的零,然后是一个非零数字,或 1 和任何数字,或 2 和从 03
  • : - 一个 : 字符
  • [0-5]\d - 012345 然后任意一个数字
  • \b - 单词边界。

如果与此正则表达式匹配,则将其作为一个整体匹配,因此您可以通过 match?.value.

访问它

如果您在匹配时不必担心任何预验证,您可以简单地匹配 3 个以冒号分隔的数字对并捕获前两个,请参见第二个正则表达式:

  • \b - 单词边界
  • (\d{1,2}:\d{2}) - 第 1 组:一位或两位数,: 和两位数
  • :\d{2} - 一个:和两个数字(未捕获)
  • \b - 单词边界。

如果匹配,我们需要第 1 组值,因此使用 match2?.groupValues?.getOrNull(1)