非贪婪正则表达式无法正常工作(Notepad++ 8.1.1)

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

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

例如,我想移动所有“Building”和“Building_something”(而不是其他 things)从 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 上我们有一堵墙,一扇门,一堵墙,草)。

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

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

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

感谢您的帮助,请记住我使用的是 Notepad++,它有时会以不同的方式处理正则表达式(例如,此处替换行中的 \) 生成 ))。

你可以找到 <thing Class="Building 然后匹配下面的两行,而不是在 ):

之前的最后一个数字之前抓取所有
<thing Class="Building(?:_[^"]*)?">(?:\R.*){2}\R.*\(.*,\h*\K104(?=\))

替换为103。见 regex demo.

详情:

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

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

改为使用以下内容:

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

(?!..)negative lookahead, which is supported per the boost syntax here。我还用给定的数据验证了 NPP ;-)

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