gpt4 book ai didi

regex - 正则表达式可以返回找到匹配项的行号吗?

转载 作者:行者123 更新时间:2023-12-04 09:31:11 25 4
gpt4 key购买 nike

在文本编辑器中,我想用找到该单词的行号的编号替换给定的单词。正则表达式可以做到这一点吗?

最佳答案

递归、自引用组(Qtax 技巧)、反向 Qtax 或平衡组

简介

在输入的底部添加一个整数列表的想法类似于一个著名的数据库黑客(与正则表达式无关),其中一个连接到一个整数表。我的原始答案使用了@Qtax 技巧。当前的答案使用递归、Qtax 技巧(直接或反向变化)或平衡组。

是的,这是可能的......有一些警告和正则表达式技巧。

  • 此答案中的解决方案旨在作为展示一些正则表达式语法的工具,而不是要实现的实际答案。
  • 在您的文件末尾,我们将粘贴以唯一分隔符开头的数字列表。对于这个实验,附加的字符串是 :1:2:3:4:5:6:7这是一种类似于使用整数表的著名数据库黑客的技术。
  • 对于前两个解决方案,我们需要一个使用正则表达式风格的编辑器,允许递归(解决方案 1)或自引用捕获组(解决方案 2 和 3)。我想到了两个:Notepad++ 和 EditPad Pro。对于第三个解决方案,我们需要一个支持平衡组的编辑器。这可能会限制我们使用 EditPad Pro 或 Visual Studio 2013+。

  • 输入文件:

    假设我们正在搜索 pig并想用行号替换它。

    我们将使用它作为输入:
    my cat
    dog
    my pig
    my cow
    my mouse

    :1:2:3:4:5:6:7

    第一个解决方案:递归

    支持的语言:除了上面提到的文本编辑器(Notepad++ 和 EditPad Pro),这个解决方案应该适用于使用 PCRE(PHP、R、Delphi)、Perl 和 Python 的语言,使用 Matthew Barnett 的 regex模块(未经测试)。

    递归结构存在于前瞻中,并且是可选的。它的工作是平衡不包含 pig 的行。 ,左边是数字,右边是:把它想象成平衡一个嵌套结构,比如 {{{ }}} ... 除了在左边我们有不匹配的行,在右边我们有数字。关键是当我们退出前瞻时,我们知道跳过了多少行。

    搜索:
    (?sm)(?=.*?pig)(?=((?:^(?:(?!pig)[^\r\n])*(?:\r?\n))(?:(?1)|[^:]+)(:\d+))?).*?\Kpig(?=.*?(?(2)\2):(\d+))

    带注释的自由间距版本:
    (?xsm)             # free-spacing mode, multi-line
    (?=.*?pig) # fail right away if pig isn't there

    (?= # The Recursive Structure Lives In This Lookahead
    ( # Group 1
    (?: # skip one line
    ^
    (?:(?!pig)[^\r\n])* # zero or more chars not followed by pig
    (?:\r?\n) # newline chars
    )
    (?:(?1)|[^:]+) # recurse Group 1 OR match all chars that are not a :
    (:\d+) # match digits
    )? # End Group
    ) # End lookahead.
    .*?\Kpig # get to pig
    (?=.*?(?(2)\2):(\d+)) # Lookahead: capture the next digits

    替换: \3
    the demo ,请参阅底部的替换。您可以使用前两行的字母(删除一个空格使 pig )移动第一次出现的 pig到不同的行,看看这如何影响结果。

    第二种解决方案:引用自身的组(“Qtax Trick”)

    支持的语言:除了上面提到的文本编辑器(Notepad++ 和 EditPad Pro),这个解决方案应该适用于使用 PCRE(PHP、R、Delphi)、Perl 和 Python 的语言,使用 Matthew Barnett 的 regex模块(未经测试)。通过转换 \K,该解决方案很容易适应 .NET。前瞻和所有格量词到原子组(请参阅下面几行的 .NET 版本。)

    搜索:
    (?sm)(?=.*?pig)(?:(?:^(?:(?!pig)[^\r\n])*(?:\r?\n))(?=[^:]+((?(1)\1):\d+)))*+.*?\Kpig(?=[^:]+(?(1)\1):(\d+))

    .NET 版本:回到 future

    .NET 没有 \K .它的位置,我们使用“回到 future ”的lookbehind(包含在比赛之前跳过的lookahead的lookbehind)。此外,我们需要使用原子组而不是所有格量词。
    (?sm)(?<=(?=.*?pig)(?=(?>(?:^(?:(?!pig)[^\r\n])*(?:\r?\n))(?=[^:]+((?(1)\1):\d+)))*).*)pig(?=[^:]+(?(1)\1):(\d+))

    带注释的自由间距版本(Perl/PCRE 版本):
    (?xsm)             # free-spacing mode, multi-line
    (?=.*?pig) # lookahead: if pig is not there, fail right away to save the effort
    (?: # start counter-line-skipper (lines that don't include pig)
    (?: # skip one line
    ^ #
    (?:(?!pig)[^\r\n])* # zero or more chars not followed by pig
    (?:\r?\n) # newline chars
    )
    # for each line skipped, let Group 1 match an ever increasing portion of the numbers string at the bottom
    (?= # lookahead
    [^:]+ # skip all chars that are not colons
    ( # start Group 1
    (?(1)\1) # match Group 1 if set
    :\d+ # match a colon and some digits
    ) # end Group 1
    ) # end lookahead
    )*+ # end counter-line-skipper: zero or more times
    .*? # match
    \K # drop everything we've matched so far
    pig # match pig (this is the match!)
    (?=[^:]+(?(1)\1):(\d+)) # capture the next number to Group 2

    替换:
    \2

    输出:
    my cat
    dog
    my 3
    my cow
    my mouse

    :1:2:3:4:5:6:7

    the demo ,请参阅底部的替换。您可以使用前两行的字母(删除一个空格使 pig )移动第一次出现的 pig到不同的行,看看这如何影响结果。

    数字分隔符的选择

    在我们的示例中,分隔符 :因为数字串很常见,并且可能发生在其他地方。我们可以发明一个 UNIQUE_DELIMITER并稍微调整一下表情。但是下面的优化更有效,让我们保留 :
    优化第二个方案:反转数字串

    不是按顺序粘贴我们的数字,以相反的顺序使用它们可能对我们有利: :7:6:5:4:3:2:1
    在我们的前瞻中,这允许我们通过简单的 .* 深入到输入的底部。 ,并从那里开始回溯。因为我们知道我们在字符串的末尾,所以我们不必担心 :digits成为字符串另一部分的一部分。这是如何做到的。

    输入:
    my cat pi g
    dog p ig
    my pig
    my cow
    my mouse

    :7:6:5:4:3:2:1

    搜索:
    (?xsm)             # free-spacing mode, multi-line
    (?=.*?pig) # lookahead: if pig is not there, fail right away to save the effort
    (?: # start counter-line-skipper (lines that don't include pig)
    (?: # skip one line that doesn't have pig
    ^ #
    (?:(?!pig)[^\r\n])* # zero or more chars not followed by pig
    (?:\r?\n) # newline chars
    )
    # Group 1 matches increasing portion of the numbers string at the bottom
    (?= # lookahead
    .* # get to the end of the input
    ( # start Group 1
    :\d+ # match a colon and some digits
    (?(1)\1) # match Group 1 if set
    ) # end Group 1
    ) # end lookahead
    )*+ # end counter-line-skipper: zero or more times
    .*? # match
    \K # drop match so far
    pig # match pig (this is the match!)
    (?=.*(\d+)(?(1)\1)) # capture the next number to Group 2

    替换: \2
    参见 the demo 中的替换.

    第三种解决方案:平衡组

    此解决方案特定于 .NET。

    搜索:
    (?m)(?<=\A(?<c>^(?:(?!pig)[^\r\n])*(?:\r?\n))*.*?)pig(?=[^:]+(?(c)(?<-c>:\d+)*):(\d+))

    带注释的自由间距版本:
    (?xm)                # free-spacing, multi-line
    (?<= # lookbehind
    \A #
    (?<c> # skip one line that doesn't have pig
    # The length of Group c Captures will serve as a counter
    ^ # beginning of line
    (?:(?!pig)[^\r\n])* # zero or more chars not followed by pig
    (?:\r?\n) # newline chars
    ) # end skipper
    * # repeat skipper
    .*? # we're on the pig line: lazily match chars before pig
    ) # end lookbehind
    pig # match pig: this is the match
    (?= # lookahead
    [^:]+ # get to the digits
    (?(c) # if Group c has been set
    (?<-c>:\d+) # decrement c while we match a group of digits
    * # repeat: this will only repeat as long as the length of Group c captures > 0
    ) # end if Group c has been set
    :(\d+) # Match the next digit group, capture the digits
    ) # end lokahead

    替换: $1
    引用
  • Qtax trick
  • On Which Line Number Was the Regex Match Found?
  • 关于regex - 正则表达式可以返回找到匹配项的行号吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23727476/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com