Vim: Как собрать все совпадающие и окружающие строки из файла?

Поскольку предложение об отдельном VimOverflow было отклонено, придется продолжить публикацию здесь.

Мне пришлось переместить переводы из одного файла в другой, только msgid соответствует какому-то определенному регулярному выражению.

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

# English.po

#: ...
msgid "..."
msgstr "..."

#: templates/common/commonTranslation.phtml:10 | These parts can be
#: any/number/of/lines/can/precede/the/data:0  | of any length.
msgid "buttonhelp.edit"                       <- Matching string
msgstr "Edit your details"                     | 
"the long line continues"                      | Translation
"and can be even longer"                       |

#: ...
msgid "..."
msgstr "..."

Вот что я сделал в Sublime:

  1. Сделал регулярное выражение для шаблона msgid, который мне нужен.
  2. Sublime помещает несколько курсоров вокруг файла.
  3. Вверх, Вверх, Shift-Вниз-Вниз-Вниз-Вниз – выделяются все блоки перевода с окружающими пустыми строками.
  4. Cmd-C, Вставить в новый файл. Готово.

Как я мог сделать это в Vim?

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

     
#: templates/common/commonTranslation.phtml:10
msgid "buttonhelp.edit" # <- value for regexp
msgstr "Edit your details"
 

Обновить Извините, сначала я этого не осознавал, но переводы могут занимать неопределенное количество строк, вот где Sublime не справился, так как я выбрал блоки фиксированного размера. Но переводы всегда отделяются пустой строкой, кроме конца файла, но это можно не учитывать. Это кратчайший возможный объем данных:

     
#~ msgid "hotline.title"  | POEdit stores obsolete
#~ msgstr "HOTLINE"       | strings as well
 

Решено Благодаря комментаторам до меня наконец дошло, и вот что я в итоге сделал:

:let @a=''
:g/\v"\w+\.\w+"/norm! "Ayap
:tabe
:put A

Сначала он очищает регистр a, находит все строки с точками между словами внутри кавычек ("\w+\.\w+") и копирует окружающие абзацы в регистр a, содержимое которого я вставляю в новую вкладку.


person firedev    schedule 09.10.2014    source источник


Ответы (2)


чтобы «выдернуть» все эти блоки в регистре a, вы можете попробовать это в vim:

:g/msgid "buttonhelp\./norm! 2kV2)"Ay

в приведенном выше :g cmd msgid "buttonhelp\. — это регулярное выражение, соответствующее вашему msgid.

перед выполнением команды :g выполните команду qaq, чтобы очистить регистр a.

person Kent    schedule 09.10.2014
comment
Спасибо, это сработало даже лучше, если бы он выбрал весь абзац, поскольку перевод мог занимать несколько строк, что я полностью пропустил в Sublime, и теперь мне пришлось бы все перепроверять:/ Однако последний перевод был полностью опущен, файл заканчивается на msgid строке без соответствующего перевода. Угадайте, что можно исправить, добавив пустую строку в конце. - person firedev; 10.10.2014
comment
Извини, не привел себя в порядок. В новом файле, который я получил после вставки буфера, последний перевод отсутствовал. Не уверен, как это было возможно, есть пустая строка, поэтому ) должно было сработать. Я проверю это позже. - person firedev; 10.10.2014
comment
Я думаю, что что-то вроде "Ayap в конце вместо 2kV2) сделало бы это даже лучше, поэтому он копирует весь блок перевода из верхней пустой строки в нижнюю. - person firedev; 10.10.2014

Вы можете найти (и выполнить команду yank) все совпадающие строки через :global.

Если вам всегда нужны строки выше и ниже строки msgid, вы можете указать их как диапазон .-1,.+1 (.+2, чтобы также включить пустую строку-разделитель).

Чтобы собрать все совпадения в регистре, сначала очистите его и используйте верхний регистр для (для добавления):

:let @a = '' | global/^msgid "\.\.\."/.-1,.+1yank A

Чтобы поместить это в другой буфер, вы можете использовать

:new | put! a
person Ingo Karkat    schedule 09.10.2014
comment
Удивительно, это сработало. Есть ли способ сначала выполнить поиск, а затем просто выполнить global с повторным указанием регулярного выражения? - person firedev; 10.10.2014
comment
Также есть способ скопировать до конца абзаца в этом случае, поскольку перевод может занимать несколько строк, на что я, к сожалению, не обращал внимания. - person firedev; 10.10.2014
comment
Вы можете опустить регулярное выражение, если вы его уже искали: :g//. Вы также можете выполнять поиск (до конца абзаца) с диапазоном, см. :h :range. - person Ingo Karkat; 10.10.2014