vim - разделяет строку запятыми и добавляет префикс к каждому токену - PullRequest
1 голос
/ 09 января 2020

У меня есть такие строки:

<prefix> <token1>, <token2>, .... <tokenN>;

, где число токенов является переменным, а каждый токен является символом или ди git.

Я хотел бы разделить их в Vim вот так:

<prefix> <token1>;
<prefix> <token2>;
...
<prefix> <tokenN>;

Я пытался получить шаблон как этот /<prefix>\s\+\(\w\+,\s*\)\{1,}\(\w\+\);/, но я не уверен, как извлечь переменное число токенов (\ 1 и \ 2 только при условии tokenN-1 и tokenN).

Мысли? Заранее спасибо.

Ответы [ 3 ]

1 голос
/ 09 января 2020

Если ваш префикс везде фиксирован (вы предлагали использовать шаблон, начинающийся с /<prefix>\s\+...), то вы, вероятно, можете использовать что-то простое:

:g/^<prefix>\s/s/,\s\+/;\r<prefix> /g

Другими словами, для каждой строки, начинающейся с <prefix>, замените все запятые (с последующим пробелом) на точку с запятой, возврат каретки и фиксированный <prefix> с последующим пробелом.


Но если предположить, что ваш <prefix> является более сложным и переменным и Вы хотите записать его в регулярное выражение:

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

Один из возможных подходов:

:s/\(\S\+\)\s\+[^,]*\zs\(,\s*[^,]*\)*\ze;$/\=substitute(submatch(0),',\s*',";\r".submatch(1)." ",'g')/

Разбивка шаблона:

  • \(\S\+\): Сопоставьте префикс в группе захвата. (Вы можете использовать что-то лучшее, более конкретное c, чем просто непробелы, чтобы правильно сопоставлять только те строки, которые вам нужны.)
  • \s\+: пропустить пробел.
  • [^,]*: Пропустить первый токен.
  • \zs: отметить начало матча. Подстановка заменяет только эту часть.
  • \(,\s*[^,]*\)*: последовательность из одного или нескольких токенов с запятой и необязательный пробел.
  • \ze: отметка конца матча.
  • ;$: сопоставить точку с запятой в конце всего этого.

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

Это достигается путем использования этих при замене:

  • \=: использовать выражение в замене (см. :help sub-replace-expression .)
  • substitute(submatch(0),',\s*',";\r".submatch(1)." ",'g'): заменить запятые (и необязательные пробелы после них) на точку с запятой, возврат каретки и префикс, а затем пробел.
  • submatch(0): мы выполнение такой замены на матче (часть между \zs и \ze только.)
  • ";\r": начало замены, точка с запятой и возврат каретки.
  • .: Оператор точки объединяет строки в Vimscript.
  • submatch(1): Относится вернуться к группе 1, которую мы использовали в этом случае для захвата префикса.
  • 'g': заменить все совпадения.

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

Техника использования * 1082 Функция * в замене :s также полезна для обработки случаев, когда групп захвата недостаточно, например, представленной вами.

0 голосов
/ 09 января 2020
0daw
:s/, /;\r/g
:'`,. normal I^R"

, где ^R набирается как Ctrl-V Ctrl-R .

Объяснение:

0       go to the start of the row
daw     delete a word (and put in the default register)
:s/     substitute
, /       a comma and a space
;\r/      with a comma and a newline
g         on the whole line
:'`,.   on each line from the one we were before to this one
normal  execute as if in normal mode
I         insert at the start of the line
^R"       the content of the default register

Или еще короче:

0yaw
:s/, /\=";\r".@"/g
0 голосов
/ 09 января 2020

Я бы сделал что-то вроде

:substitute/, /;\r/g

Чтобы изменить запятые на; -newline, затем использовать некоторую форму селектора диапазона (:global или визуальный режим, скорее всего), чтобы сделать

:[range]substitute/^/prefix
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...