vim-如何选择多行?

时间:2019-04-15 08:26:38

标签: 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 + 复制,转到最后一行并创建一个新行,粘贴并突出显示所有新行,然后按 + < kbd> SHIFT + l ,然后添加我想要的任何内容。

我正在使用vim multiple cursors,但不确定是否要这样做。有方向吗?

4 个答案:

答案 0 :(得分:3)

有很多方法可以做到。这是一个:从第一个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
: $<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$<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)

答案 1 :(得分:0)

这就是我要做的:

首先,用替换创建回声线:

:%s/\(db_\w\+\)=\$(echo "\w\+")/&\recho "\1: $\1"

请注意替换中的&,这是整个匹配的行。后跟\r以换行。

然后,清空您将用于它的寄存器(在我的情况下为a

qaq

然后在该寄存器中剪切所有回显线:

:g/^echo /d A

最后,转到您想要的位置,然后粘贴寄存器的内容:

"ap

答案 2 :(得分:0)

稍微不同的解决方案:

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

使用替代命令代替普通命令

第二个命令可以是替换

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

vim解决方案如何成为更智能的解决方案?

如果您要更改成百上千的行,我认为多个游标将无济于事,尤其是当图案在多行上交错时。

答案 3 :(得分:0)

也许我错过了您想做的事情,但如果我理解正确,您只是想更新输出格式。

尝试一下:

: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”。 我的“拍子”是您的(echo ",我的“ cmd”是替补。

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

我说用echo "..."...代替,并记住引号之间的含义是1,后面是2。

替换部分说先放回所有内容(echo "\1"\2),然后再放一点点装饰。

通过点击 CTRL-V ,我进入了报价模式,这使我可以点击 CTRL-M 插入回车符vim会在执行时转换为换行符,至少在我使用的版本上会转换为换行符。

这是一个把戏。知道和使用它可能很方便,但是请始终牢记,这些东西基本上都是黑客。 Caveat脚本编写者。

接下来,我使用格式为echo "\1: $\1"的格式添加所需的行。