Regexp-replace: несколько замен в матче

Я конвертирую наш проект MVC3 в использование T4MVC. И я хотел бы заменить java-скрипт включает в себя работу с 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 regexps. Я могу найти имя скрипта и заменить его этими регулярными выражениями:

найти: ("~/Scripts/(.*)")

заменить на (Scripts.)

но я не могу понять, как заменить точки и тире в именах файлов в подчеркивания и заменить прямые косые черты в точки.

Я могу проверить, что JS-filename имеет точку или тире в имени с этим

 ("~/Scripts/(?=.*)(?=-*).*")

но как заменить группы внутри группы?

нужно иметь не жадную замену внутри группы и иметь эти замены в порядке, поэтому прямые косые черты, преобразованные в точку, не будут преобразованы в подчеркивание после этого.

Это не критическая проблема, я уже сделал все замены вручную, но я думал, что я хорош с regexp, поэтому эта проблема меня беспокоит!!

p.s. предпочтительным инструментом является Notepad++, но любое решение POSIX regexp будет делать -)

п.С. С. здесь вы можете получить образец вещей, которые будут заменены и вот этот текст

4 ответов


я бы просто использовал сайт, как RegexHero

  1. вы можете передать код в поле целевой строки, а затем поместить (?<=(~/Script).*)[.-](?=(.*"[)]")) на и . на


вот решение vanilla Notepad++, но это, конечно, не самый элегантный. Мне удалось выполнить преобразование с несколькими проходами над файлом.

первый проход

заменить . и - С _.

найти: ("~/Scripts[^"]*?)[.-]

Заменить На: _

к сожалению, я не мог найти способ, чтобы соответствовать только на . или -, потому что он потребует назад, что по-видимому, не поддерживается Notepad++. Из-за этого каждый раз, когда вы выполняете замену только первый . или - в скрипте имя будет заменено (поскольку совпадения не могут перекрываться). Следовательно, вы должны запустить эту замену несколько раз, пока не будет сделано больше замен (в вашем примере ввода это будет 8 раз).

второй этап

заменить / С ..

найти: ("~/Scripts[^"]*?)/

заменить: .

это в основном то же самое, что и первый проход, только с разными символами (вам придется это 3 раза для примера файла). Выполнение проходов в этом порядке гарантирует, что никакие косые черты не закончатся как подчеркивания.

Третий этап

удалите окружающие символы.

найти: "~/(Scripts[^"]*?)"

заменить на:

теперь это будет соответствовать всем именам сценариев, которые все еще окружены by "~/ и ", захватывая то, что находится между ними, и просто выводя это.

обратите внимание, что, включив окружающие символы в шаблоны поиска первых двух проходов, вы можете избежать преобразования . в строках, которые уже в новом формате.

как я уже сказал, это не самый удобный способ, чтобы сделать это. Тем более, что проходы один и два должны выполняться вручную несколько раз. Но это все равно сэкономит много времени для больших файлов, и я не могу придумать способ получить их все-только в правильных строках-за один проход, без возможностей поиска. Конечно, я бы очень приветствовал предложения по улучшению этого решения :). Надеюсь, я мог бы, по крайней мере, дать вам (и всем, у кого есть подобная проблема) отправную точку.


если, как показывает ваш вопрос, вы хотите использовать n++, используйте N++ Python Script. Настройте сценарий и назначьте комбинацию клавиш, затем у вас есть однопроходное решение, требующее только открытия, Изменения и сохранения... проще и быть не может.

Я думаю, что часть проблемы заключается в том, что N++ - это не инструмент regex и использовать специальное средство для regex , или даже решение поиска/замены, иногда гарантируется. Вы можете быть лучше, как в скорости, так и в значение времени использование инструмента для обработки текста и редактирования.

[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 Script
  2. новый скрипт:: Плагины - > скрипт Python - > script-name.py
  3. выберите вкладку цель.
  4. Run:: Plugins - > скрипт Python - > скрипты- > script-name

[Edit: расширенный однострочная команда PythonScript]

имея потребность в новом модуле regex для Python (который, я надеюсь, заменяет re), я поиграл и скомпилировал его для использования с плагином 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, чтобы установить полное содержимое буфера на результаты скомпилированной команды подстановки регулярных выражений, по существу, используя "выключение" имени группы, которая не пуста.

надеюсь Дэйв (автор PythonScript) добавит модуль regex в ExtraPythonLibs часть проекта.


в качестве альтернативы вы можете использовать сценарий, который будет делать это и избегать копирования вставки и остальной ручной работы в целом. Рассмотрите возможность использования следующего скрипта:

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

и запустите его так:

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

все файлы с расширением .ext будет отредактирован на месте, а исходные файлы будут сохранены с помощью