Вопрос по – Объединить несколько строк (два блока) в Vim

322

Я хотел бы объединить два блока строк в Vim, то есть взять строкиn..m и добавить их в строкиa..b, Если вы предпочитаете объяснение псевдокода:[a[i] + b[i] for i in min(len(a), len(b))]

Пример:

abc
def
...

123
45
...

должен стать

abc123
def45

Есть ли хороший способ сделать это без ручного копирования и вставки?

Смотрите аналогичный вопрос (и ответ!)here NWS
Нет, у меня есть два отдельных блока. ПСЕВДОКОД-иш:[a[i] + b[i] for i in min(len(a), len(b))] ThiefMaster♦
Итак ... вы хотите присоединиться к чередующимся линиям? То есть вы хотите присоединиться к линииx с присоединениемx+2? larsks

Ваш Ответ

9   ответов
3

Я бы просто поставил virtualedit на
(:set virtualedit=all)
Выберите блок 123 и все ниже.
Поместите это после первого столбца:

abc    123
def    45
...    ...

и удалите несколько пробелов между 1 пробелом:

:%s/\s\{2,}/ /g
Error: User Rate Limit ExceededgvV:'<,'>s/\s+//gError: User Rate Limit Exceeded'<,'>Error: User Rate Limit Exceeded
3

:1,4s/$/\=getline(line('.')+4)/ | 5,8d
8

выбор блока - это путь. Но вы также можете использовать любой вариант:

:!tail -n -6 % | paste -d '\0' % - | head -n 5

Этот метод основан на командной строке UNIX.paste Утилита была создана для обработки такого слияния строк.

PASTE(1)                  BSD General Commands Manual                 PASTE(1)

NAME
     paste -- merge corresponding or subsequent lines of files

SYNOPSIS
     paste [-s] [-d list] file ...

DESCRIPTION
     The paste utility concatenates the corresponding lines of the given input files, replacing all but the last file's newline characters with a single tab character,
     and writes the resulting lines to standard output.  If end-of-file is reached on an input file while other input files still contain data, the file is treated as if
     it were an endless source of empty lines.
Error: User Rate Limit Exceededpaste -dError: User Rate Limit Exceededmy answer.
Error: User Rate Limit Exceeded ThiefMaster♦
44

Go to the third line: jj Enter visual block mode: CTRL-v Anchor the cursor to the end of the line (important for lines of differing length): $ Go to the end: CTRL-END Cut the block: x Go to the end of the first line: kk$ Paste the block here,: p

Движение не самое лучшее (я не эксперт), но оно работает так, как вы хотели. Надеюсь, что будет более короткая версия.

Вот предварительные условия, чтобы этот метод работал хорошо:

All lines of the starting block (in the example in the question abc and def) have the same length XOR the first line of the starting block is the longest, and you don't care about the additional spaces in between) XOR The first line of the starting block is not the longest, and you additional spaces to the end.
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded:%s/ \+/ /g
set ve=allError: User Rate Limit Exceededvimdoc.sourceforge.net/htmldoc/options.html#'virtualeditError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded ThiefMaster♦
Error: User Rate Limit ExceededabcError: User Rate Limit ExceededdefError: User Rate Limit Exceeded
55

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

:1,g/^/''+m.|-j!

Для подробного объяснения используемой техники, см.ответ Я дал вопрос & quot;Vim paste -d & apos; & APOS; поведение из коробки?& Quot ;.

Error: User Rate Limit Exceeded ThiefMaster♦
E16: Invalid RangeError: User Rate Limit Exceeded1,Error: User Rate Limit Exceeded ThiefMaster♦
Error: User Rate Limit Exceeded ThiefMaster♦
Error: User Rate Limit Exceededsil!Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded:moveError: User Rate Limit Exceeded:join!Error: User Rate Limit Exceeded''Error: User Rate Limit Exceeded:help ''Error: User Rate Limit Exceeded+Error: User Rate Limit Exceeded-Error: User Rate Limit Exceeded:help rangeError: User Rate Limit Exceeded
19

qama:5<CR>y$'a$p:5<CR>dd'[email protected]

Вам нужно знать две вещи:

The line number on which the first line of the second group starts (5 in my case), and the number of lines in each group (3 in my example).

Вот что происходит:

qa records everything up to the next q into a "buffer" in a. ma creates a mark on the current line. :5<CR> goes to the next group. y$ yanks the rest of the line. 'a returns to the mark, set earlier. $p pastes at the end of the line. :5<CR> returns to the second group's first line. dd deletes it. 'a returns to the mark. jq goes down one line, and stops recording. [email protected] repeats the action for each line (3 in my case)
Error: User Rate Limit Exceeded[Enter]Error: User Rate Limit Exceeded:5Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded:norm qama:5<CR>y$'a$p:5<CR>dd'[email protected]Error: User Rate Limit Exceededq. ThiefMaster♦
Error: User Rate Limit Exceeded:let @a="ma:5^My$'a$p:5^Mdd'aj" | normal [email protected]Error: User Rate Limit Exceeded^MError: User Rate Limit Exceeded
1

используя любой из следующих двух методов.

предположим, что первый блок находится в строке 1, а второй блок начинается со строки 10 с начальной позиции курсора в строке номер 1.

(\ n означает нажатие клавиши ввода.)

1. abc
   def
   ghi        

10. 123
    456
    789

с макросом, используя команды: копировать, вставить и присоединиться.

qaqqa:+9y\[email protected]

с помощью макроса с помощью команд переместите строку на номер n-й строки и присоединитесь.

qcqqc:10m .\[email protected]

881

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

Если вы хотите сделать это простобывший команды

:5,8del | let l=split(@") | 1,4s/$/\=remove(l,0)/

преобразует

work it 
make it 
do it 
makes us 
harder
better
faster
stronger
~

в

work it harder
make it better
do it faster
makes us stronger
~

UPDATE: Ответ с таким большим количеством голосов заслуживает более подробного объяснения.

В Vim вы можете использовать символ трубы (|) для объединения нескольких команд Ex, поэтому приведенное выше эквивалентно

:5,8del
:let l=split(@")
:1,4s/$/\=remove(l,0)/

Многие команды Ex принимают диапазон строк в качестве аргумента префикса - в приведенном выше случае5,8 передdel и1,4 передs/// укажите, над какими строками работают команды.

del удаляет указанные строки. Он может принимать аргумент регистра, но когда он не задан, он сбрасывает строки в безымянный регистр,@"так же, как удаление в обычном режиме.let l=split(@") затем разбивает удаленные строки в список, используя разделитель по умолчанию: пробел. Для правильной работы с вводом, который имеет пробелы в удаленных строках, например:

more than 
hour 
our 
never 
ever
after
work is
over
~

нам нужно указать другой разделитель, чтобы "работа не была" от разделения на два элемента списка:let l=split(@","\n").

Наконец, в заменs/$/\=remove(l,0)/заменяем конец каждой строки ($) со значением выраженияremove(l,0). remove(l,0) меняет списокl, удалив и вернув первый элемент. Это позволяет нам заменять удаленные строки в том порядке, в котором мы их читаем. Вместо этого мы могли бы заменить удаленные строки в обратном порядке, используяremove(l,-1).

Error: User Rate Limit Exceededs/\s*$/Error: User Rate Limit Exceededs/$/.
Error: User Rate Limit Exceeded:help range, :help :d, :help :let, :help split(), :help :s, :help :s\=, :help remove().
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded:sil5,8del | let l=split(@") | sil1,4s/$/\=remove(l,0)/ | call histdel("/", -1) | nohlsError: User Rate Limit Exceeded ThiefMaster♦
2

Учитывая это:

aaa
bbb
ccc

AAA
BBB
CCC

С курсором на первом «а» в первой строке нажмите следующее:

qq}jdd''$pkJj0q

а затем нажмите@q (и вы можете впоследствии использовать@@) столько раз, сколько нужно.

Вы должны в конечном итоге:

aaaAAA
bbbBBB
cccCCC

(Плюс перевод строки)

Похожие вопросы