Список номеров строк в качестве входных данных для vim - PullRequest
0 голосов
/ 29 ноября 2018

У меня есть список номеров строк в файле, например:

1
5
3

Я хочу добавить один и тот же комментарий к каждому из этих номеров строк в другом файле:

test1 # comment
test2 # comment
test3
test4
test5 # comment

IsЕсть ли способ обрабатывать файл построчно как ввод для номера строки в vim и выполнять над ним некоторые операции?Я знаю, как настроить таргетинг на одну строку, используя

5,5s/$/ # comment/ 

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

Ответы [ 4 ]

0 голосов
/ 29 ноября 2018

Вы также можете использовать сгенерированный скрипт sed:

sed 's:$:s/$/ # comment/:' line_nums | sed -f- infile

Сгенерированный скрипт выглядит так:

1s/$/ # comment/
5s/$/ # comment/
3s/$/ # comment/

А вывод из второго sed выглядит следующим образомэто:

test1 # comment
test2
test3 # comment
test4
test5 # comment
0 голосов
/ 29 ноября 2018

Учитывая извлечение списка, уже выполненного - см. Ответ Инго.

Если у вас не так много строк и индексов, следующее должно быть достаточно быстрым (оно должно быть быстрее, чем :global решение)

:call setline(1, map(range(1, max(list)), 'index(list, v:val) >=0 ? printf("test%d # comment", v:val) : v:val'))

Если число строк и индексов значительно возрастет, я не уверен, что это решение O (N²) будет масштабироваться.Поскольку :for петли медленные, я не уверен, как мы могли бы действовать эффективно, если бы в нашем распоряжении были инструменты.

Может быть:

:let d = {}
:call map(copy(list), 'extend(d, {v:val: printf("test%d # comment", v:val)})')
:call setline(1, map(range(1, max(list)), 'get(d, v:val, v:val)'))

, который окончательно запутан

Еще один запутанный O (N) путь - это

:call sort(list)
:call setline(1, map(range(1, slist[-1]), 'v:val == slist[0] ? printf("test%d # comment", remove(slist, 0)) : v:val'))
0 голосов
/ 29 ноября 2018

Звучит как работа для Awk.

:%!gawk 'NR == FNR {a[$0] = " \#comment"; next} FNR in a { $0 = $0 a[FNR]} 1' lines.txt -

Программа awk расширена для удобства чтения:

NR == FNR {
    a[$0] = " #comment";
    next
}

FNR in a {
    $0 = $0 a[FNR]
}

1

Основная идея заключается в том, что мы отправляем два файла в awk, lines.txt и стандартный (-).В файле lines.txt мы сохраняем номер строки в массиве a, с комментарием в качестве значения (a[$0] = " #comment";).При переходе через stdin обновите строку, если номер строки находится внутри нашего массива (FNR in a).Затем распечатайте каждую строку stdin (1)

ПРИМЕЧАНИЕ. Я использую gawk, поэтому ваш пробег может отличаться.Также должен выйти, #, поскольку Vim расширяет его до альтернативного буфера.

0 голосов
/ 29 ноября 2018

Вы можете создать список Vim из файла:

let list = readfile('path/to/list.txt')

или, если файл был открыт в Vim:

let list = getbufline('list.txt', 1, '$')

Это даст вам:

:echo list
['1', '5', '3']

В качестве второго шага нам нужно найти подходящие строки.for цикл будет делать;номер строки будет интерполирован через :execute:

for l in list
    execute l . 's/$/ # comment/'
endfor

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

global/^/if index(list, "" . line('.')) != -1 | s/$/ # comment/ | endif
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...