vim — как выбрать несколько строк?

#vim

#vim

Вопрос:

Допустим, у меня есть этот текст:

 #!/bin/bash
# Get host
db_host=$(echo "dbhost") 
# Get DB name
db_name=$(echo "dbname")
# Get user
db_user=$(echo "dbuser")
# Get password
db_pass=$(echo "dbpass")
 

и я хочу выбрать имя каждой переменной и создать этот вывод под текстом:

 echo "db_host: $db_host"
echo "db_name: $db_name"
echo "db_user: $db_user"
echo "db_pass: $db_pass"
 

Например, в sublime я бы выделил =$( и нажал d несколько раз, вернулся к началу строки, скопировал с SHIFTпомощью , перешел к последней строке и создал новую, вставил, выделил все новые строки, нажал SHIFTl, а затем добавил все, что я хочу.

Я использую vim multiple cursors , но я не уверен, что это правильный путь. Какие-либо указания?

Комментарии:

1. Вы имеете в виду преобразовать этот текст в новый или дополнительно создать новый текст? Это весь текст? Ширина переменных всегда одинакова ?… Есть много направлений, которые вы могли бы предпринять…

2. 1, что мне удалось сделать, это записать макрос. qd0v почему goecho «<esc>pA: $ <esc>pA»q

3. Добавьте текст в тот же файл, на 1 строку ниже последней строки. Это весь текст. ширина должна быть одинаковой (1 w движение для выбора имени переменной). Мне удалось сделать это с помощью макроса, но это заняло больше времени, чем хотелось бы.

4. Почему вы используете подоболочку echo для присвоения этих простых строк переменным?

5. @PaulHodges Отличный вопрос, хотя и не связанный с настоящим: P

Ответ №1:

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

 yGGp              Yank everything, paste at the bottom
:.,$g/^#/d<CR>    In the pasted part, remove all comment lines
<C-O>             Back to start of the pasted part
<C-V>GI           Select the first column, prepend
echo "<Esc>
f=<C-V>           Then select the block from equals to quote, change
f"Gc
:

lt;Esc>
f)<C-V> Then select the block at the closing brace, change
G$c
;<Esc>

Другой подход, использующий макросы и регистры, начиная с той же позиции:

 qqq               Clear register q
qwq               Clear register w
qq                Start recording macro in q
yaw               yank a word (db_name) to default register
o                 open a new line below, and start insert
echo "
<C-R>"            insert the content of the default register (db_name)
: $
<C-R>"            insert the content of the default register (db_name) again
"<Esc>
"Wdd              the line is done; yank-append to register w
j0                skip the comment line, position at the start of the next variable
@q                execute the q macro (which is currently empty, but not for long)
q                 save the q macro
@q                execute the q macro (which will recurse, and slurp up all lines)
"wp               paste all the accumulated lines at the bottom
 

Третий, с использованием регулярного выражения:

 :.,$v/^#/t

lt;CR> copy all non-comment lines to the end
:-3,.s/(w ).*/echo "1: $1"/<CR>
I didn't set a mark so manual range from 3 lines above:
capture the first word, discard everything else,
replace with what we want (obviously, could have done
visual selection instead of manually setting range)

Ответ №2:

Вот как я бы это сделал:

Сначала создайте эхо-строки с заменой:

 :%s/(db_w )=$(echo "w ")/amp;recho "1: $1"
 

Обратите amp; внимание на замену, которая представляет собой всю согласованную строку. Затем r для новой строки.

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

 qaq
 

Затем вырежьте все эхо-строки в указанном регистре:

 :g/^echo /d A
 

Наконец, перейдите туда, где вы хотите, чтобы они были, и вставьте содержимое регистра:

 "ap
 

Ответ №3:

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

Попробуйте это:

 :g/[(]echo "/s/echo "([^"]*)"(.*)$/echo "1"2^Mecho "1: $1"/
 

Обратите ВНИМАНИЕ: ^M — это один управляющий символ, а НЕ карат, а затем M.
Смотрите ниже.

Перед —

 #!/bin/bash
# Get host
db_host=$(echo "dbhost")
# Get DB name
db_name=$(echo "dbname")
# Get user
db_user=$(echo "dbuser")
# Get password
db_pass=$(echo "dbpass")
 

После —

 #!/bin/bash
# Get host
db_host=$(echo "dbhost")
echo "dbhost: $dbhost"
# Get DB name
db_name=$(echo "dbname")
echo "dbname: $dbname"
# Get user
db_user=$(echo "dbuser")
echo "dbuser: $dbuser"
# Get password
db_pass=$(echo "dbpass")
echo "dbpass: $dbpass"
 

Объяснение

 :g/[(]echo "/s/echo "([^"]*)"(.*)$/echo "1"2^Mecho "1: $1"/
 

по частям —

 :g/pat/cmd
 

Это говорит «глобально» на каждой строке, соответствующей «pat», «cmd».
Мой «pat» был вашим (echo " , а мой «cmd» — это замена.

 s/echo "([^"]*)"(.*)$/echo "1"2^Mecho "1: $1"/
 

Я сказал заменить echo "..."... и запомнить, что было между кавычками как 1, и что-нибудь после 2.

В части замены говорится, что нужно вернуть все, что там было ( echo "1"2 ), за которым следует немного придирок.

Нажав CTRL-V, я перешел в режим кавычек, что позволило мне нажать CTRL-M, чтобы вставить возврат каретки, который vim при выполнении преобразуется в новую строку, по крайней мере, в тех версиях, которые я использовал.

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

Я последовал за этим с помощью форматирования echo "1: $1" , чтобы добавить нужные строки.

Комментарии:

1. Ctrl-V — это не хакерство, это обычная (и полезная для понимания) часть Vim: :help c_ctrl-v

2. Хм. Я использовал трюк из командной строки. Я не понимал, что трюк, который я использовал в командной строке, вероятно, был связан с настройками set -o vi , лол

Ответ №4:

Немного другое решение:

 :g/echo/t$
:-3,.normal! ywccecho "<Ctrl-v><Ctrl-r>0:

lt;Ctrl-v><Ctrl-r0"

Объяснение

 :g ................... global command
/echo/ ............... applied on each line that has "echo"
t$ ................... copy to the end
 

Курсор переместится в конец, поэтому мы устанавливаем интервал в минус три строки до текущей строки -3,.

 yw ................... copy the first word
cc ................... start chnanging the whole line
echo " ............... inserts a literal `echo "`
Ctrl-v Ctrl-r 0 ...... inserts the word we copied
 

Примечание: Чтобы вставить нулевой регистр 0 , мы должны ввести Ctrl-vCtrl-r0

Использование команды замены вместо обычной

Вторая команда может быть заменой

 :-3,.s/v(^w ).*/echo "1: $1"
 

Как решение vim может быть более разумным решением?

Если у вас есть сотни или тысячи строк для изменения, я думаю, что несколько курсоров не очень помогут, особенно если шаблон чередуется с несколькими строками.