14

У меня большой XML-файл

<obj param="2542">
<obj param="2333">
<obj param="6433">

Мне нужно увеличить все значения "param" на некоторое число. Я могу сопоставить числа, которые мне нужны, с помощью поиска регулярных выражений во многих редакторах, но как применить некоторую математику к замене?

3 ответа3

18

Немного потрудившись, выясняется, что vim может сделать это одной командой без сценариев. Например, чтобы добавить 50 ко всем числам, следующим за <obj param=" вы можете использовать:

:%s@<obj param="\(\d\+\)@\='<obj param="' . (submatch(1) + 50)@g

Позвольте мне сломать это.

: это общий способ войти / показать режим командной строки в vim.

% означает в рамках всего документа; Вы можете ввести диапазон чисел, например, 1,50 чтобы сделать это в первых 50 строках.

s является сокращением от замены (вы можете написать целое слово, если хотите)

@ - разделитель; Вы можете использовать любой другой символ, если он не в том, что вы ищете. Просто используйте это три раза. (Синтаксис похож на sed .)

Все до следующего вхождения разделителя @ является шаблоном reg ex для поиска, в данном случае <obj param=" за которым следует \d\+ , что является любым количеством цифр. \( И \) предназначены для установки всей этой последовательности цифр в виде одной группы reg ex, которая будет соответствовать обратным ссылкам, таким как \1 , или команде vim submatch .

Затем разделитель @ помечает то, что следует за текстом замены.

\= В начале здесь означает замену результата некоторого вычисляемого выражения, а не шаблона или строки reg ex, которые здесь являются ключевыми.

Тогда у нас есть '<obj param="' для начала замещающего текста. . Далее следует функция vim для объединения строк.

submatch(1) - это встроенная функция vim, которая может использоваться только внутри команды подстановки и возвращает строку, которая совпадает с регулярным выражением \1 ; вы бы использовали submatch(2) для эквивалента регулярного выражения \2 и так далее. (\0 - это весь сопоставленный шаблон, но мы не хотим этого здесь.) \( И \) в шаблоне поиска используются, чтобы отметить то, что считается submatch(1) .

Следовательно (submatch(1) + 50) дает результат прибавления 50 к числу, за которым следуют цифры после <obj param=" в форме шаблона поиска.

Разделитель @ снова используется для выделения конца текста замены.

Флаг g используется для того, чтобы сделать замены глобальными; Вы можете пропустить это, если хотите заменить только первый экземпляр в каждой строке.

Вы можете, вероятно, решить, как складывать разные числа, вычитать, делить и т.д.

7

В Emacs (начиная с версии 23): используйте \, чтобы выполнить произвольный код на Лиспе при замене регулярного выражения. Например, чтобы возвести в квадрат числа, которые вы могли бы использовать

M-x replace-regexp
param="\([0-9]+\)"
param="\,(* \#1 \#1)"

В Vim: начните замену текста с \= (см . :help sub-replace-special). Например, чтобы возвести в квадрат числа:

s!param="\([0-9]\+\)"!\='param="'.submatch(1)*submatch(1).'"'!

Несколько редакторов позволяют вам делать такие вещи с макросами: определить макрос, который 1. ищет следующее совпадение и 2. выполняет замену (используя внешний инструмент для арифметики, если необходимо); Повторите макрос столько раз, сколько у вас совпадений.

1

Вы можете использовать Vim, чтобы сделать это для вас. Просто откройте свой файл и запишите макрос. Пример: поиск по любому номеру

/[0-9]{1,}

затем нажмите q и a (сохранить макрос в регистре a). После этого нажмите Ctrl-X (увеличив число на 1) и затем нажмите n (для следующего результата поиска). После этого нажмите q еще раз, чтобы сохранить макрос. Теперь вы можете применить макрос к следующему номеру, нажав @+a. Это изменит текущий номер и перейдет к следующему. Повторяя это или используя x @ a, вы можете повторить это x раз.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .