如何在字符串中多次匹配一个模式并替换它们

huangapple go评论64阅读模式
英文:

How to match a pattern multiple times within a string and replace them

问题

我想要找到所有在 #include 预处理指令中的 Foo 实例,使用正则表达式。到目前为止,我只能匹配一个实例,使用以下模式 #include "(.*?)Foo(.*?)",并将 Foo 替换为 Bar 我使用以下替换 #include "$1Bar$2"

当我将 Foo 替换为 Bar 时,以下示例

#include "abcFoo1/Foo123/aFoo"

变成了

#include "abcBar1/Foo123/aFoo"

我卡在尝试弄清如何使其匹配 #include 语句内的所有 Foo 实例并在替换后获得以下结果。

#include "abcBar1/Bar123/aBar"

P.S. 我试图在诸如 Notepad++ 或 Visual Studio 等文本编辑器中执行此操作,用于许多字符串。

英文:

I want to find all instances of Foo inside #include preprocessor using regex. so far, I can only match one instance using this pattern #include "(.*?)Foo(.*?)". and to replace Foo with Bar i use this substitution #include "$1Bar$2"

When I replace Foo with Bar, the following example

#include "abcFoo1/Foo123/aFoo"

becomes

#include "abcBar1/Foo123/aFoo"

I'm stuck trying to figure out how to make it match all instances of Foo within the #include statement and get the following result after replacement.

#include "abcBar1/Bar123/aBar"

P.S. I'm trying to do this for many strings using a text editor such as Notepad++ or IDE like Visual Studio.

答案1

得分: 2

以下是翻译好的部分:

您可以在例如Notepad++(或任何使用PCRE的工具)中使用此正则表达式,如果您想一次完成此操作:

(?:#include ".*?|(?<!^)\G.*?)\KFoo

解释:

  • (?:#include ".*?|(?<!^)\G.*?) - 非捕获组,有两个备选项:
  1. #include ".*? - 您字符串的开头,后面跟着非贪婪匹配的任何内容。
  2. (?<!^)\G.*? - \G 是前一次匹配结束的位置,后面跟着与上面相同的非贪婪匹配。在这里使用\G 是必要的,否则正则引擎不会匹配相同的部分两次。(?<!^) 是前行否定断言,用于不匹配在#include之上有Foo的情况(因为\G从字符串的开头开始),这种情况不应该发生,可能是可选的,但为了完整的解决方案而包括在内。
  • \K - 不要包括此之前的任何内容在匹配中,这样只有下一个部分会被匹配。
  • Foo - 您要替换的部分

我们只匹配Foo,所以替换应该是Bar

此外,在Notepad++中,需要关闭“. matches newline”选项。

演示和详细说明

英文:

You can use this regex in e.g. Notepad++ (or anything that uses PCRE) if you want to do it in one go:

(?:#include ".*?|(?<!^)\G.*?)\KFoo

Breakdown:

  • (?:#include ".*?|(?<!^)\G.*?) - non-captured group with 2 alternatives:
  1. #include ".*? - the start of your string followed by non-greedily matched anything
  2. (?<!^)\G.*? - \G is the position at the end of previous match, followed by non-greedy anything as above. Using \G is required here, since otherwise the regex engine won't match the same parts twice. (?<!^) negative lookbehind of the start of the line is there to not match cases in which there would be something with Foo above #includes (as \G starts at the start of the string), which shouldn't happen and is likely optional, but included it just in case, for a full solution.
  • \K - don't include anything before this in the match, so that only the next part gets matched
  • Foo - the part that you want to replace

We're matching only Foos, so the replacement should be just Bar.

Also, in Notepad++, . matches newline option needs to be turned off.

Demo with detailed explantation

答案2

得分: 1

在Notepad++或Sublime Text中,您点击Ctrl+H,会弹出查找+替换栏,
您在查找字段中输入Foo,然后在替换字段中输入Bar,就可以了。

我相信不需要复杂的正则表达式模式。

英文:

On Notepad++ or Sublime text, you click Ctrl+H, you get the find+replace bar,
you write Foo in the find field, then Bar in the Replace, and it should be good.

no need for a complex regex pattern I believe.

答案3

得分: 0

Instead of looking for a string with Foo to replace it with Bar, look for Foo which has #include behind

(?=Foo)(?<=#include .*)Foo

or

Foo(?<=#include .*Foo)
英文:

Instead of looking for a string with Foo to replace it with Bar, look for Foo which has #include behind

(?=Foo)(?&lt;=#include .*)Foo

or

Foo(?&lt;=#include .*Foo)

答案4

得分: 0

如果文件名应该被双引号括起来,并且你不想匹配单独的双引号:

(?:#include\h+&quot;(?=[^&quot;\r\n]*&quot;)|\G(?!^))[^&quot;\r\n]*?\KFoo

解释

  • (?: 非捕获组,用于提供多个替代项
    • #include\h+&quot; 匹配 #include 后面跟着1个或多个水平空白字符
    • (?=[^&quot;\r\n]*&quot;) 正向预查,断言在同一行右边有一个 &quot;
    • |
    • \G(?!^) 断言当前位置在前一次匹配的末尾,而不是字符串的开头
  • ) 关闭非捕获组
  • [^&quot;\r\n]*? 匹配除了 &quot; 或换行符之外的可选字符
  • \KFoo 忘记之前匹配的内容,然后匹配 Foo

正则表达式演示

如果字符串不应该包含空格,你可以在否定字符类中使用 \s

(?:#include\h+&quot;(?=[^&quot;\s]*&quot;)|\G(?!^))[^&quot;\s]*?\KFoo

正则表达式演示

英文:

If the filename should be between double quotes, and you don't want to match crossing a double quote by itself:

(?:#include\h+&quot;(?=[^&quot;\r\n]*&quot;)|\G(?!^))[^&quot;\r\n]*?\KFoo

Explanation

  • (?: Non capture group for the alternatives
    • #include\h+&quot; Match #include followed by 1+ horizontal whitespace chars
    • (?=[^&quot;\r\n]*&quot;) Positive lookahead, assert a &quot; to the right on the same line
    • | Or
    • \G(?!^) Assert the current position at the end of the previous match, not at the start of the string
  • ) Close the non capture goru
  • [^&quot;\r\n]*? Match optional chars other than &quot; or a newline
  • \KFoo Forget what is matches so far and match Foo

Regex demo

If the string should not contain spaces, you can use \s in the negated character class:

(?:#include\h+&quot;(?=[^&quot;\s]*&quot;)|\G(?!^))[^&quot;\s]*?\KFoo

Regex demo

huangapple
  • 本文由 发表于 2023年5月7日 04:11:59
  • 转载请务必保留本文链接:https://go.coder-hub.com/76190925.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定