非贪婪正则表达式无法像我想要的那样工作 (Notepad++ 8.1.1)

Non-greedy regex not working like I would like (Notepad++ 8.1.1)

提问人:oli_vi_er 提问时间:8/5/2021 最后编辑:oli_vi_er 更新时间:8/5/2021 访问量:294

问:

我在 Windows 10 上使用 Noteapd++ v8.1.1 来编辑游戏 Rimworld 中的保存文件,以更改地图上物品的位置。

例如,我想将所有“Building”和“Building_something”(而不是其他东西s)从y=104移动到y=103,在不同项目的列表中(这里,坐标的形式为(x,0,y),我简化了代码并添加了行号):

58  <thing Class="Plant">
59      <def>Plant_TreeOak</def>
60      <id>Plant_TreeOak41339</id>
61      <pos>(100, 0, 105)</pos>
62   </thing>
63   <thing Class="Building">
64      <def>Wall</def>
65      <id>Wall28005</id>  
66      <pos>(101, 0, 105)</pos>
68   </thing>
69   <thing Class="Building">
70      <def>Wall</def>
71      <id>Wall29667</id>
72      <pos>(103, 0, 105)</pos>
74   </thing>
75   <thing Class="Building">
76      <def>Wall</def>
77      <id>Wall28005</id>
78      <pos>(101, 0, 104)</pos>
80   </thing>
81   <thing Class="Building_Door">
82      <def>Door</def>
83      <id>Door642106</id>
84      <pos>(102, 0, 104)</pos>
86   </thing>
87   <thing Class="Building">
88      <def>Wall</def>
89      <id>Wall29667</id>
90      <pos>(103, 0, 104)</pos>
92   </thing>
93   <thing Class="Plant">
94      <def>Plant_Grass</def>
95      <id>Plant_Grass203219</id>
96      <pos>(104, 0, 104)</pos>
97   </thing>

(在这里,在y=105上,我们有一棵橡树,一堵墙,什么都没有,一堵墙;在y=104上,我们有一堵墙,一扇门,一堵墙,一堵草)。

我尝试找到(单行)并将其替换为 . 对于此示例,第一个匹配项从第 69 行开始,到第 78 行结束,而我希望它从第 75 行开始(接下来的两个匹配项工作正常)。<thing Class="Building(.*?)104\)<thing Class="Building$1103\)

我尝试了很多东西,寻找准确的文档,但无济于事(我什至找不到Notepad ++使用的正则表达式引擎...... 实际上,我认为我不完全理解“非贪婪”正则表达式的工作原理。

请注意,英语不是我的母语,所以技术英语有时对我来说很棘手。

感谢您的帮助,请记住,我正在使用 Notepad++,它有时处理正则表达式的方式略有不同(例如,在这里,在替换行中制作 ).\))

正则表达式 记事本++ 非贪婪

评论

0赞 Wiktor Stribiżew 8/5/2021
NPP 使用 Boost 正则表达式库。
0赞 Wiktor Stribiżew 8/5/2021
使用和替换为 ,请参阅正则表达式演示<thing Class="Building(?:_[^"]*)?">(?:\R.*){2}\R.*\(.*,\h*\K104(?=\))103
0赞 oli_vi_er 8/5/2021
谢谢 Wiktor,您的正则表达式也与第 96 行 (104, 0, 104) 中的 x(水平)104 匹配。@user2864740:这样写似乎不起作用,但我正在研究那个“?!
0赞 Wiktor Stribiżew 8/5/2021
它与第 96 行上的任何内容都不匹配。有,所以没有匹配。我的正则表达式仅匹配第 78、84 和 90 行,请确保您使用的是我的正则表达式。thingClass="Plant"
0赞 Wiktor Stribiżew 8/5/2021
使用正确的设置查看我的答案。

答:

0赞 Wiktor Stribiżew 8/5/2021 #1

您可以找到并匹配下面的两行,然后抓住最后一个数字之前的所有:<thing Class="Building)

<thing Class="Building(?:_[^"]*)?">(?:\R.*){2}\R.*\(.*,\h*\K104(?=\))

替换为 .请参阅正则表达式演示。103

细节

  • <thing Class="Building- 固定字符串
  • (?:_[^"]*)?- 一个 char 的可选序列,后跟除 char 之外的零个或多个 char_"
  • ">- 固定字符串
  • (?:\R.*){2}- 两条线
  • \R- 换行符序列
  • .*- 0+ 字符,除了 line brea 字符之外,尽可能多的字符
  • \(- 一个字符(
  • .*- 0+ 字符,除了 line brea 字符之外,尽可能多的字符
  • ,\h*- 逗号和 0+ 水平空格
  • \K- match reset 运算符丢弃到目前为止匹配的所有文本
  • 104- 固定值
  • (?=\))- 下一个 char 必须是 .)

enter image description here

评论

0赞 oli_vi_er 8/5/2021
只是一个问题:当我将 regex101 用于 NPP 时,我必须勾选“PCRE (PHP <7.3)”?
0赞 Wiktor Stribiżew 8/5/2021
@oli_vi_er这两个选项都可以,您在这里不需要任何特定的 PCRE 仅正则表达式功能。
0赞 user2864740 8/5/2021 #2

正则表达式是懒惰的。在给定的起始位置,这是最小的有效匹配。

请改用以下命令:

<thing Class="Building(?:(?!<thing).)*?104\)

这是一个负面的展望根据此处的 boost 语法支持。我还用给出的数据验证了它 NPP ;-)(?!..)

可以在 https://www.mobzystems.com/online/explain-regular-expression/ 生成正则表达式的扩展解释。

评论

1赞 Wiktor Stribiżew 8/5/2021
我已经修复了脾气暴躁的贪婪令牌语法,必须在前瞻之后放置.
0赞 user2864740 8/5/2021
@WiktorStribiżew 感谢您的更新。但是,这两种方法似乎都在本地返回相同的匹配项 - 我想知道在什么情况下会导致不同的匹配项。
0赞 Wiktor Stribiżew 8/5/2021
当右边紧跟着左边时。这是一个非常罕见的情况,在这里可能永远不会成为问题,但 TGT 必须正确编写。