Regexp-replace:匹配中的多个替换

时间:2012-10-08 12:00:32

标签: regex notepad++ replace t4mvc

我正在将我们的MVC3项目转换为使用T4MVC。我想替换java-script包也可以使用T4MVC。所以我需要替换

"~/Scripts/DataTables/TableTools/TableTools.min.js"
"~/Scripts/jquery-ui-1.8.24.min.js"

进入

Scripts.DataTables.TableTools.TableTools_min_js
Scripts.jquery_ui_1_8_24_min_js

我目前正在使用Notepad ++作为regexp工具,它正在使用POSIX正则表达式。 我可以找到脚本名称并将其替换为这些正则表达式:

查找:\("~/Scripts/(.*)"\)

替换为\(Scripts.\1\)

但我无法弄清楚如何将文件名中的点和短划线替换为下划线并将正斜杠替换为点。

我可以通过此

检查js-filename在名称中是否有点或短划线
 \("~/Scripts/(?=\.*)(?=\-*).*"\)

但是如何替换组内的组?

需要在群组中进行非贪婪的替换,并且这些替换会按顺序进行,因此转换为点的正斜杠不会在之后转换为下划线。

这是一个非关键问题,我已经手动完成了所有替换,但我认为我对regexp很好,所以这个问题让我感到困扰!!

P.S。首选工具是Notepad ++,但任何POSIX正则表达式解决方案都可以 - )

p.p.s。 Here you can get a sample要替换的东西 And here is the the target text

4 个答案:

答案 0 :(得分:3)

这是一款香草Notepad ++解决方案,但它肯定不是最优雅的解决方案。我设法通过文件多次传递进行转换。

第一次通过

.-替换为_

查找:("~/Scripts[^"]*?)[.-]

替换为:\1_

很遗憾,我找不到匹配 .-的方法,因为它需要一个lookbehind,这显然是Notepad ++不支持的。因此,每次执行替换时,只会替换脚本名称中的第一个.-(因为匹配不能重叠)。因此,您必须多次运行此替换,直到不再进行替换(在您的示例输入中,这将是8次)。

第二次通过

/替换为.

查找:("~/Scripts[^"]*?)/

替换为:\1.

这与第一遍基本相同,只是使用不同的字符(示例文件需要3次)。按此顺序执行传递可确保不会将斜杠作为下划线结束。

第三次通过

删除周围的字符。

查找:"~/(Scripts[^"]*?)"

替换为:\1

现在,这将匹配仍被"~/"包围的所有脚本名称,捕获介于两者之间的内容并仅输出该内容。

请注意,通过在前两个传递的查找模式中包含那些周围的字符,您可以避免在已经是新格式的字符串中转换.

正如我所说,这不是最方便的方法。特别是,由于第一和第二遍必须多次手动执行。但它仍然可以为大型文件节省大量时间,而且我无法想到一种方法来获取所有这些 - 只在正确的字符串中 - 一次通过,没有外观能力。当然,我非常欢迎建议改进这个解决方案:)。我希望我至少可以给你(以及任何有类似问题的人)作为起点。

答案 1 :(得分:3)

如果您的问题表明,您想使用N ++,那么请使用N ++ Python Script。设置脚本并分配一个快捷键,然后你有一个只需要打开,修改和保存的单一通过解决方案......不能比这简单得多。

我认为问题的一部分是N ++是正则表达式工具和使用专用的正则表达式工具 有时甚至是搜索/替换解决方案。使用用于文本处理和编辑的工具,你在速度和时间价值方面可能会更好。

[Script Edit] ::改变以匹配修改后的进/出期望。

# Substitute & Replace within matched group.
from Npp import *
import re

def repl(m):
    return "(Scripts." + re.sub( "[-.]", "_", m.group(1) ).replace( "/", "." ) + ")"

editor.pyreplace( '(?:[(].*?Scripts.)(.*?)(?:"?[)])',  repl )
  1. 安装::插件 - >插件管理器 - > Python脚本
  2. 新脚本::插件 - > Python脚本 - > script-name.py
  3. 选择目标标签。
  4. 运行::插件 - > Python脚本 - >脚本 - >脚本的名称

  5. [编辑:扩展的单行PythonScript命令]

    需要Python的新正则表达式模块(我希望替换它)我玩了并编译它以使用N ++ PythonScript插件并决定在您的样本集上测试它。

    控制台上的两个命令最终在编辑器中显示正确的结果。

    import regex as re
    editor.setText( (re.compile( r'(?<=.*Content[(].*)((?<omit>["~]+?([~])[/]|["])|(?<toUnderscore>[-.]+)|(?<toDot>[/]+))+(?=.*[)]".*)' ) ).sub(lambda m: {'omit':'','toDot':'.','toUnderscore':'_'}[[ key for key, value in m.groupdict().items() if value != None ][0]], editor.getText() ) )
    

    很甜蜜!

    使用regex代替re还有什么真正的好处是我能够在Expresso中构建表达式并按原样使用它!通过将r''字符串部分复制粘贴到Expresso中,可以对其进行详细说明。

    其缩写文本为::

    Match a prefix but exclude it from the capture. [.*Content[(].*]
    [1]: A numbered capture group. [(?<omit>["~]+?([~])[/]|["])|(?<toUnderscore>[-.]+)|(?<toDot>[/]+)], one or more repetitions
        Select from 3 alternatives
             [omit]: A named capture group. [["~]+?([~])[/]|["]]
                 Select from 2 alternatives
                     ["~]+?([~])[/]
                     Any character in this class: ["]
             [toUnderscore]: A named capture group. [[-.]+]
             [toDot]: A named capture group. [[/]+]
    Match a suffix but exclude it from the capture. [.*[)]".*]
    

    命令细分非常好,我们告诉Scintilla将完整的缓冲区内容设置为编译的正则表达式替换命令的结果,主要是使用非空的组名称的“switch”。 / p>

    希望Dave(PythonScript作者)将正则表达式模块添加到项目的ExtraPythonLibs部分。

答案 2 :(得分:3)

我会使用像RegexHero

这样的网站
  1. 您可以将代码传递到目标字符串框中,然后将(?<=(~/Script).*)[.-](?=(.*"[)]"))放入Regular Expression框中_框中的Replacement String

  2. 完成替换后,点击底部的Final String,然后选择Move to target string and start a new expression

  3. 从那里,将(?<=(<script).*)("~/)(?=(.*[)]" ))|(?<=(Url.).*)(")(?=(.*(\)" )))粘贴到Regular Expression框中,并将Replacement String框留空。

  4. 完成替换后,点击底部的Final String,然后选择Move to target string and start a new expression

  5. 从此处将(?<=(Script).*)[/](?=(.*[)]"))粘贴到Regular Expression框,将.粘贴到Replacement String框中。

  6. 之后,Final String框将显示您要查找的内容。我不确定你可以解析多少文本的上限,但如果这是一个问题,它可能会被分解。我确信可能有更好的方法来做到这一点,但这往往是我这样做的方式。我喜欢这个网站的一个原因是因为我不需要安装任何东西,所以我可以在任何地方快速完成。

    编辑1:根据评论,我已将步骤3移至步骤5并添加了新的步骤3和4.我必须这样做,因为新的步骤5将替换/ "~/Scripts 1}}使用.,打破"~/的删除。我还必须更改第5步的代码,以便考虑Script

    的更改开头

答案 3 :(得分:2)

或者你可以使用一个脚本来完成它并避免复制粘贴和其余的手工劳动。请考虑使用以下脚本:

$_.gsub!(%r{(?:"~/)?Scripts/([a-z0-9./-]+)"?}i) do |i| 
    'Scripts.' + $1.split('/').map { |i| i.gsub(/[.-]/, '_') }.join('.')
end

然后像这样运行:

$ ruby -pi.bak script.rb *.ext

所有扩展名为.ext的文件都将进行就地编辑,原始文件将以.ext.bak扩展名保存。如果您使用版本控制(并且您应该),那么您可以使用一些可视化差异工具轻松查看更改,必要时进行更正并在之后提交。

相关问题