正则表达式,在 char 之前获取 char

Regex, get char after char before char

提问人:Espada 提问时间:10/10/2023 最后编辑:InSyncEspada 更新时间:10/10/2023 访问量:158

问:

样本:

[Foo][Bar]Foo bar foo bar: foo; bar: foo bar foo bar __
[Foo][Bar]Foo; bar: foo bar __ foo bar foo bar
[Foo]Foo bar foo bar foo bar: foo __ bar; foo bar __ foo bar
[Bar]Foo; bar; foo

例如,我有一个如上所示的字符串格式。

我想问的是,如何获取分号(不是空格或空格)之后的字母,而是第一个冒号之前的字母?;:

如果可能的话,我想使用正则表达式一步标记字母

我想得到的字母以粗体标记

*作为附加信息,我想将字母更改为大写。

正则表达式 vb.net

评论

0赞 Espada 10/10/2023
在上面的示例中,是的,但在原始数据中,它可能有所不同。
0赞 Ted Lyngmo 10/10/2023
等一下。。。您只想捕获一个字母吗?不是字母
0赞 Jimi 10/10/2023
像这样的东西 ?-- 从描述中不清楚为什么最后一行应该匹配,而不是第一行中的第三行,而第二行与描述匹配;\s*(\w)(?=.*:)bar:
0赞 Espada 10/10/2023
是的,就像我在问题中给出的示例字符串一样,我在需要捕获的字母上加粗标记。
1赞 Ted Lyngmo 10/10/2023
并请解释为什么你期望并被捕获。那里根本没有冒号。bf[Bar]Foo; bar; foo

答:

0赞 Ted Lyngmo 10/10/2023 #1
^[^;:]*;\s*(.).*:
  • ^- 线锚点的起点
  • [^;:]*- 匹配除零次或多次之外的任何东西;:
  • ;- 在文字上匹配;
  • \s*- 零个或多个空格的匹配
  • (.)- 捕获一个角色
  • .*- 在任何字符上匹配零次或多次
  • :- 匹配文字冒号

演示


既然你也说你想要并被捕获,那么实际上似乎不需要冒号。bf[Bar]Foo; bar; foo

这是一个将捕获和:bf

^(?:[^;:]*;\s*(.))+
  • ^- 线锚点的起点
  • (?:- 非捕获组的开始
    • [^;:]*- 匹配任何字符,但零次或更多次;:
    • ;- 在文字上匹配;
    • \s*- 在空格上匹配零次或更多次
    • (.)- 捕获一个角色。如果不允许将其替换为([^:]):
  • )- 非捕获组结束
  • +- 匹配非捕获组 1 次或更多次

演示

评论

0赞 Espada 10/10/2023
我已经尝试了您的代码,但正如我所说,我想在分号之后但在第一个冒号之前获得 1 个字母或 1 个单词(无关紧要)。第一个冒号后面的分号不包括在内,也不考虑在内。
0赞 Ted Lyngmo 10/10/2023
@Espada好的,如果我理解正确,更新应该可以工作。在示例字符串中,只有第二行有一个匹配项。
0赞 Jotne 10/10/2023
我猜 OP 会想要 how 这个词,不仅仅是一个字母,而是字母
0赞 Ted Lyngmo 10/10/2023
@Jotne这是我的第一个想法,但OP不在乎它只是一个字母还是一个单词。请参阅此处的第一条评论。此外,在 OP 的原始版本中,它只捕获了一个字母。
0赞 Jotne 10/10/2023
好的,但是这一行中也有一个粗体 B,但没有 :,所以不确定什么是正确的。[Bar]Foo; bar; foo
1赞 InSync 10/10/2023 #2

使用两个环视从要匹配的字符中排除周围环境:

(?<=              # Match something preceded by
  ^[^:]*;\s*      # the start of the line, 0 or more non-colons, a semicolon and any whitespaces
)                 # that is
[^\s:]            # not a colon and not a whitespace
(?=               # which must be followed by
  [^:]*(?:$|:)    # 0 or more non-colons, then either the end of the line or the first colon.
)                 # 

在 regex101.com 上试用。

[^:], , 并且从不匹配冒号,因此 lookahead 中的冒号与该行的第一个冒号匹配。如果没有冒号,我们只需回退到行尾,从而允许主表达式匹配。;\s[^\s:]

正则表达式需要具有多行修饰符 (/)。我不知道 VB.NET,但以下片段似乎有效:(?m)RegexOptions.Multiline

Sub Main()
  Dim regex As New Regex("(?<=^[^:]*;\s*)[^\s:](?=[^:]*(?:$|:))", RegexOptions.Multiline)
  Dim input As String =
    "[Foo][Bar]Foo bar foo bar: foo; bar: foo bar foo bar __" & vbCrlf &
    "[Foo][Bar]Foo; bar: foo bar __ foo bar foo bar" & vbCrlf &
    "[Foo]Foo bar foo bar foo bar: foo __ bar; foo bar __ foo bar" & vbCrlf &
    "[Bar]Foo; bar; foo"
  
  Console.WriteLine(regex.Replace(input, AddressOf ConvertToUppercase))
End Sub

Function ConvertToUppercase(match As Match) As String
  Return match.Groups(0).Value.ToUpper()
End Function

在 ideone.com 上试用。

评论

0赞 InSync 10/10/2023
在撰写本文时,regex101.com 向大多数请求返回 504,因此可能无法访问该链接。
0赞 Ted Lyngmo 10/10/2023
不过,我手动输入了您的内容,它似乎捕获了与 OP 给出的示例相同的内容。+1(?<=^[^:]*;\s*)[^\s:](?=[^:]*(?:$|:))^(?:[^;:]*;\s*(.))+
0赞 InSync 10/10/2023
@TedLyngmo谢谢。老实说,我确实认为我的更适合替换,因此更适合 OP 的目标,即将这些字符替换为大写版本。
0赞 Ted Lyngmo 10/10/2023
不知道。所有以一种或另一种方式工作的替代方案都是好的 - 也许这其中有一个微妙的区别,对 OP 更有效。我认为最好使用常规 VB 函数将它们大写。我在 .net 正则表达式引擎中找不到任何可以自动执行此操作的东西,但也许它在某个地方。
0赞 Espada 10/10/2023
@InSync 经过 2 天的寻找,终于......正则表达式和 vb.net 代码运行良好,正如我所期望的那样。非常感谢:-)