Сменить текст вокруг знака равенства

Есть ли простой способ перевернуть код вокруг знака равенства в vi/vim?

Например: я хочу это сделать:

value._1 = return_val.delta_clear_flags;
value._2._1 = return_val.delta_inactive_time_ts.tv_sec;
value._2._2 = return_val.delta_inactive_time_ts.tv_nsec;
value._3    = return_val.delta_inactive_distance_km;
(...)

в это:

return_val.delta_clear_flags = value._1;
return_val.delta_inactive_time_ts.tv_sec = value._2._1;
return_val.delta_inactive_time_ts.tv_nsec = value._2._2;
return_val.delta_inactive_distance_km = value._3;
(...)

в LOT строк в файле.

Я знаю, что это кажется немного тривиальным, но я часто сталкивался с множеством случаев, когда кодировал, где мне нужно было это делать в прошлом, и у меня никогда не было хорошей идеи/способа сделать это, не требовал много ввода в vim или писал awk script. Я бы подумал, что это возможно с помощью одного лайнера в vi.

Пояснения к однострочным линиям очень приветствуются и будут сильно рассмотрены, когда я выберу свой принятый ответ.:)

Ответ 1

Что-то вроде этого:

:%s/\([^=]*\)\s\+=\s\+\([^;]*\)/\2 = \1

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

EDIT: Объяснение

Мы используем команду s/ find / replace. Эта часть найдет нас:

  • самая длинная строка, состоящая из знаков ничего, но равных, выраженная [^=]*...
  • ... за которым следует одно или несколько пробелов, \s\+ (дополнительный \ перед + - это vim oddity)
  • ... затем = и снова любое количество пробелов, =\s\+
  • ... за которым следует самая длинная строка символов с точкой с запятой, [^;]*

Затем мы запишем пару скобок для сохранения материала, который нам понадобится, чтобы построить заменяющую строку, что синтаксис \( stuff \)

И, наконец, мы используем захваченные строки в заменяющей части команды s/ find / replace: \1 и \2.

Ответ 2

Для интереса, вот как я сделал это как записанный макрос:

qq0"+df=xA<BACKSPACE> = <ESC>"+pxi;<ESC>jq

Формирование того, что на первой строке устанавливает макрос "q" для выполнения необходимых действий. Затем на каждой последующей строке вы можете выполнить макрос, набрав:

@q

или, скажем, вы хотите применить макрос к следующим 10 строкам:

[email protected]

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

Изменить. Дэн Олсон указывает в своем комментарии, что если вы хотите применить макрос к ряду строк, например строки 6-100, вы можете ввести следующее. Я не знаю, есть ли более сжатый синтаксис, который не требует соответствия шаблону ". *".

:6,100g/.*/normal @q

Объяснение макроса

  • кв.кв
    • начать запись в регистр q
  • 0
    • перейти к началу строки
  • "+ ДФ =
    • удалить до '=' и поместить текст в регистр "+"
  • х
    • удалить лишнее пространство
    • перейти к концу строки и войти в режим вставки
  • <BACKSPACE>= <ESC>
    • Удалить точку с запятой, вставить знак равенства и пробел
  • "+ р
    • вставьте тест, скопированный ранее в регистр '+'
  • XI <ESC>
    • вставьте конечную точку с запятой
  • J
    • переместитесь на следующую строку, чтобы повторно применить макрос
  • д
    • остановить запись

Ответ 3

:%s/^\s*\(.\{-}\)\s*=\s*\(.\{-}\)\s*;\s*$/\2 = \1;/

должен работать хорошо.

Ответ 4

:%s/\([^ =]*\)\s*=\s*\([^;]*\);/\2 = \1;/