我有一个 XML 文件(1000 条记录,这里简化了),结构(例如):
<LIST>
<ITEM_0>
<NAME>Item Name</NAME>
</ITEM_0>
...
<ITEM_9999>
<NAME>Item Name</NAME>
</ITEM_9999>
</LIST>
我需要结果:
<LIST>
<ITEM>
<ID>0</ID>
<NAME>Item Name</NAME>
</ITEM>
...
<ITEM>
<ID>9999</ID>
<NAME>Item Name</NAME>
</ITEM>
</LIST>
使用正则表达式:
Find: \<ITEM_(.*)(>)
Replace: ITEM>\n<ID>\1\</ID>
我得到:
<LIST>
<ITEM>
<ID>0</ID>
<NAME>Item Name</NAME>
</ITEM>
<ID>0</ID> <-- This line not wanted
...
<ITEM>
<ID>9999</ID>
<NAME>Item Name</NAME>
</ITEM>
<ID>9999</ID> <-- This line not wanted
</LIST>
它正在取代</ITEM>
以及尽管(我认为)我要求它只替换<ITEM>
- 我做错了什么/如何修复?我可能遗漏了有关分组(或“贪婪”?)的某些内容,但不确定是什么,并且到处寻找类似内容。有无数种方法可以用其他东西来切割和切块,但使用 NPP 却如此接近却没有到达,这让我很烦。
感谢帮助-谢谢。
后期编辑:即使我让第一个替换工作正常,只是标签<ITEM_#>
,我仍然需要将</ITEM_#>
结束标签作为另一个搜索/替换操作。这里的问题是当前操作替换两个都和<ITEM
标签</ITEM
...
答案1
是的,很可能是.*
太“贪婪”了,捕获了尽可能多的字符尽可能地;你需要相反的——最短的匹配。
一种方法是使用[^>]*
代替——这仍然会匹配尽可能多的内容,但只匹配到第一个>
,因此<ITEM_([^>]*)>
只会匹配开始标签,仅此而已。
根据正则表达式语法,.*?
也可能有效 - 这明确地将其切换*
为“非贪婪”。
答案2
感谢 Gravity,它帮助我扩大了搜索范围这里在一个正则表达式中涵盖多个搜索和替换。
尝试以下方法可行:
Find: </ITEM_.*(>)|<ITEM_(.*)(>)
Replace: (?1</ITEM>)(?2<ITEM>\n<ID>\2</ID>)
RegEx
| 分隔要查找的两个字符串,而 ?1 和 ?2 分别是它们的替换值。
但我必须先查找结束</ITEM
标记,而不是<ITEM
您逻辑上认为的标记。所以我有一个解决方案,但有人能回答这个问题吗?为什么上面的方法有效,而下面的方法(先查找<ITEM
标记)在我们只是反转查找顺序时失败了?
Find: <ITEM_(.*)(>)|</ITEM_.*(>)
Replace: (?1<ITEM>\n<ID>\1</ID>)(?2</ITEM>
RegEx
不是必需的,但好奇的人可能想知道。谢谢。
答案3
- Ctrl+H
- 找什么:
<ITEM_(\d+)>([\s\S]*)</ITEM_\1>
- 用。。。来代替:
<ITEM>\n<ID>$1</ID>$2</ITEM>
- 查看 相符
- 查看 环绕
- 查看 正则表达式
- 取消选中
. matches newline
- Replace all
解释:
<ITEM_ # literally
(\d+) # group 1, 1 or more digits, you can use [^>]* if other characters than digits are allowed
> # literally
([\s\S]*) # group 2, 0 or more any character, including linebreaks
</ITEM_ # literally
\1 # backreference to group 1
> # literally
替代品:
<ITEM> # literally
\n # linefeed, use \r\n for windows EOL
<ID>$1</ID> # ID tag, with the content of group 1
$2 # content of group 2
</ITEM> # literally
截图(之前):
截图(之后):