如何在多行文本块上使用 Xcode 的“查找和替换”

How can I use Xcode's `Find and Replace` on Multiline blocks of text

我有一个包含数百个文本块(部分 C++ 方法调用)的大文件,类似于下面的 Current 块,我希望使用 Xcode's正则表达式替换 将每个更改为类似于下面的 Desired 块,捕获值 0.89f、名称、0.1、0.5 和 2。

请注意,这两个块分别以 new Zapp//d.p.’s to show 开始和结束,因此为了节省手动编辑的工作量,我希望使用正则表达式搜索和替换。

我面临的主要问题是 multi-line 块的性质。如果我们暂时忽略它,我几乎已经在以下 single-line 个块上执行了搜索和替换:

当前:

new Zapp (0.89f // defaultParameterValue , "A name" // name , 0.1 // min , 0.5 // max , 2 // d.p.'s to show

期望:

new Zapp (NormalisableRange<float> (0.1, 0.5) ,NormalisableRange<float> (0.1, 0.5).convertTo0to1(0.89f) , "A name" // name , 2 // d.p.'s to show

查找和替换:

查找Zapp\s+\((.*)\s+// defaultParameterValue\s+,\s+"(.*)"\s+\/\/\s+name\s+,\s+(.*)\s+\/\/\s+min\s+,\s+(.*)\s+\/\/\s+max\s+,\s+(.*)\s+\/\/\s+d.p.'s

替换Zapp (NormalisableRange<float> (, ) ,NormalisableRange<float> (, ).convertTo0to1() , "" // name , // d.p.’s

单行解决方案存在捕获1(1space)、捕获3(4 spaces) 并捕获 5 (3 spaces),否则效果很好:

我尝试使用 [^\s]+ 从捕获 1 (0.89f)、捕获 3 (0.1) 和捕获 5 (2) 中消除白色 space 但它没有帮助所以如果有人可以指出原因,我将不胜感激。

我可以使用 \s+ 搜索 upperlower,但我无法将它们放在一起来获得所需的结果。

我在网上看到一些旧帖子暗示 Xcode 可能无法完成此任务。如果这是真的,有人可以建议一种替代方法来完成这项工作吗?

原因是 .* 太贪心了,匹配了 \s+ 模式可以匹配的空白,但对于这个贪婪的子模式。

要么使用 lazy/reluctant .*?:

Zapp\s+\((.*?)\s+// defaultParameterValue\s+,\s+"(.*)"\s+\/\/\s+name\s+,\s+(.*?)\s+\/\/\s+min\s+,\s+(.*?)\s+\/\/\s+max\s+,\s+(.*?)\s+\/\/\s+d.p.'s

regex demo

或者定义 class 来匹配 floats/integers [-+\w.]+(有点不精确,但是因为期望值类型已知所以可以)或者双引号文字("([^"\]*(?:\.[^"\]*)*)"):

Zapp\s+\(([-+\w.]+)\s+// defaultParameterValue\s+,\s+"([^"\]*(?:\.[^"\]*)*)"\s+\/\/\s+name\s+,\s+([-+\w.]+)\s+\/\/\s+min\s+,\s+([-+\w.]+)\s+\/\/\s+max\s+,\s+([-+\d.]+)\s+\/\/\s+d.p.'s

another demo

请看Wiktor的回答。他给出了两个解决方案和demo,总体上解决了问题。

不过,感谢 Rich 的回答 Multi line search and replace tool, I discovered AppCode by JetBrains 确实会进行多行搜索和替换:

搜索:

new Zapp\s+\(([^\s]+)\s+// defaultParameterValue\n\s+"(.*)"\s+\/\/\s+name\s+, ([^\s]+)\s+// min\n,\s+([^\s]+)\s+// max\n,\s+([^\s]+)\s+// d.p.'s to show

替换:

new Zapp (NormalisableRange<float> (, )\n\t ,NormalisableRange<float> (, ).convertTo0to1()\n\t\t\t , "" // name\n\t\t\t , // d.p.'s to show