有时我想跨多行编辑某个视觉文本块。
例如,我会采用如下所示的文本:
name
comment
phone
email
让它看起来像这样
vendor_name
vendor_comment
vendor_phone
vendor_email
目前我现在做的方式是......
按 V 键,然后按四次 j,选择块的所有 4 行。使用 > 缩进。用 h 返回一个字母。使用 Ctrlv 进入阻止视觉模式。按四次 j 向下选择四行。此时您已经选择了一个 4x1 的可视空白块(四行一列)。按 C。注意这几乎向左缩进了一列。键入不带引号的“ vendor_”。注意我们不得不放回的额外空间。按 Esc。这是我使用 Esc 退出插入模式的极少数情况之一。 Ctrlc 只会编辑第一行。重复步骤 1。使用 < 以另一种方式缩进。
如果单词前至少有一列空格,我不需要缩进。如果我不必用 c 清除可视块,我就不需要空格。
但是,如果我必须清除,那么有没有办法在不使用缩进创建所需空白的情况下执行我上面执行的操作?
另外,为什么一次编辑多行只能通过使用 Esc over Ctrlc 退出插入模式?
这是一个更复杂的例子:
name = models.CharField( max_length = 135 )
comment = models.TextField( blank = True )
phone = models.CharField( max_length = 135, blank = True )
email = models.EmailField( blank = True )
至
name = models.whatever.CharField( max_length = 135 )
comment = models.whatever.TextField( blank = True )
phone = models.whatever.CharField( max_length = 135, blank = True )
email = models.whatever.EmailField( blank = True )
在此示例中,我将在 .
上执行垂直视觉块,然后在插入模式下重新插入,即键入 .whatever.
。希望现在您可以看到这种方法的缺点。我仅限于选择一列在垂直位置上都相同的文本。
:s/models\./\0whatever./
将光标移动到名称中的 n。进入可视块模式 (Ctrlv)。按 j 三次(或 3j)向下跳 3 行; G(大写 g)跳到最后一行 按 I(大写 i)。输入供应商_。注意:它只会更新第一行的屏幕 - 直到按下 Esc (6.),此时所有行都将更新。按 Esc。
https://i.stack.imgur.com/T1WBi.gif
必须使用大写的 I
而不是小写的 i
,因为小写的 i
被解释为 text object 的开头,这本身就非常有用,例如在标签块内进行选择({ 2}):
https://i.stack.imgur.com/nlwsZ.gif
另一种方法是将 . (dot
) 命令与 i 结合使用。
将光标移动到您想要开始的位置 按 i 键入您想要的前缀(例如 vendor_) 按 esc。按 j 下一行 Type 。重复上一次编辑,再次自动插入前缀 在 j 和 . 之间快速交替。
我发现这种技术对于少量添加通常比可视块模式更快,并且具有额外的好处,如果您不需要在范围内的每一行上插入文本,您可以通过按额外的 j 轻松跳过它们。
请注意,对于大量连续添加,块方法或宏可能会更好。
使用 CtrlV 选择要修改的行。按: I:在所选内容之前插入。 A:在选择的内容之后追加。 c:替换选择的内容。键入新文本。按 Esc 将更改应用到所有选定的行。
Esc
- 我花了一段时间才弄清楚这些更改会“稍后”传播!
v
不起作用?我可以用 Ctrl+V --> A
做到这一点,但是用 v
来选择文本不起作用—— A
只附加到该行。不是都选吗?另外,很奇怪——如果我将视觉块延伸到行尾,A
只会附加到行尾;否则它会附加到每一行的可视块结束的任何地方。就像它无法识别 a
和 A
之间的区别。
c
而不是 C
,但效果非常好。谢谢
我会使用宏来记录我的动作,然后重复它。
将光标放在名称的第一个字母上。点击 qq 开始记录到 q 缓冲区。按 i 进入插入模式,键入 vector_,然后按 Esc 退出插入模式。现在点击 0 回到行首。现在按 j 下去。现在再次按 q 停止录制。
你现在有一个不错的宏。
键入 3@q 以执行您的宏 3 次以执行其余的行。
:%s/^/vendor_/
还是我错过了什么?
vender_
前缀的许多其他行。
1,4s/^/vendor_/
V
直观地阻止选择并输入 :
。它将在 ed 表达式前面加上 :'<,'>
,这使得 ed 仅适用于带有 :'<,'>s/^/vendor_/
的选择
:noh
。
2016 年 1 月更新
虽然接受的答案是一个很好的解决方案,但实际上击键次数略少,并且可以更好地扩展 - 原则上基于接受的答案。
将光标移动到名称中的 n。进入可视块模式 (ctrlv)。按 3j 按 I。输入 vendor_。按 ESC。
https://i.stack.imgur.com/ce8e1.gif
请注意,这比提供的接受答案的击键次数更少(比较第 3 步)。我们只计算要执行的 j 个动作的数量。
如果您启用了行号(如上图所示),并且知道您希望移动到的行号,则可以将步骤 3 更改为 #G,其中 # 是所需的行号。
在我们上面的示例中,这将是 4G。然而,当只处理几个行号时,显式计数效果很好。
可以更灵活的替代方案:
示例:在行首输入文本 XYZ
:%norm IXYZ
这里发生了什么事?
% == 在每一行执行
norm == 在普通模式下执行以下键
== 在行首插入
XYZ == 你要输入的文字
然后你按 Enter 键,它就会执行。
具体到您的要求:
:%norm Ivendor_
您还可以选择特定范围:
:2,4norm Ivendor_
或在选定的可视范围内执行:
:'<,'>norm Ivendor_
或为匹配“目标”正则表达式的每一行执行:
:%g/target/norm Ivendor_
ctrl-v ctrl-[
插入“转义 Esc”,这会将您拉回“正常模式”以执行正常命令。我刚刚用 '<,'>norm Iaa^[ysiw"
对此进行了测试,其中 ^[
是转义的 Esc。
:%mode
方法非常值得了解。我很高兴我偶然发现了这个答案!
我想在只有vi(没有nano)的服务器上注释掉一些配置文件中的很多行,所以视觉方法也很麻烦我是这样做的。
打开文件 vi 文件 显示行号 :set number!或者 :set number 然后使用行号将行首替换为“#”,如何?
:35,77s/^/#/
注意:数字包括在内,从 35 到 77 的行,包括的都将被修改。
要取消注释/撤消它,只需使用 :35,77s/^#//
如果你想在每一行代码之后添加一个文本词作为注释,你也可以使用:
:35,77s/$/#test/
(适用于 Python 等语言)
:35,77s/;$/;\/\/test/
(适用于 Java 等语言)
学分/参考:
https://unix.stackexchange.com/questions/84929/uncommenting-multiple-lines-of-code-specified-by-line-numbers-using-vi-or-vim https://unix.stackexchange.com/questions /120615/how-to-comment-multiple-lines-at-once
您可能还有一个用例,您想删除一段文本并替换它。
像这样
Hello World
Hello World
至
Hello Cool
Hello Cool
您可以在两行中仅视觉块选择“世界”。
键入 c 进行更改 - 现在您将处于插入模式。
插入你想要的东西并点击逃生。
两者都会垂直反射。它就像“I”一样工作,只是它用新文本替换块而不是插入它。
假设你有这个文件:
something
name
comment
phone
email
something else
and more ...
您想在“name”、“comment”、“phone”和“email”前面添加“vendor_”,无论它们出现在文件中的什么位置。
:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc
c
标志将提示您进行确认。如果你不想要提示,你可以放弃它。
Use Ctrl+V to enter visual block mode
Move Up/Down to select the columns of text in the lines you want to comment.
Then hit Shift+i and type the text you want to insert.
Then hit Esc, wait 1 second and the inserted text will appear on every line
Ctrl + v 进入可视块模式 使用向上和向下箭头选择行 输入小写 3i(按小写字母 I 三次) I(按大写 I。这将带您进入插入模式。)写下您要添加的文本Esc 按向下箭头
我来这里是为了在多行中粘贴一个已经复制的字符串。当使用 y
复制时,我们可以粘贴,在 INSERT MODE 中,按 Ctrl+r 并在按 '' 之后立即粘贴。这将与处于正常模式下的结果相同,然后按 p。这称为从注册表粘贴。
假设缓冲区中有以下文本:
vendor_something
text
to_receive
the_paste
pattern
然后我们可以将光标指向 vendor_ 中的 v 并按 v,使用 l 向右移动,直到选择我们要粘贴在下面的文本中的下划线符号。之后,我们可以将光标指向“text”的开头(vendor_something下面的两行)并按Ctrl+v。然后 I
进入插入模式,我们按 3j
Ctrl+r '' Esc。此序列的结果将是:
vendor_something
vendor_text
vendor_to_receive
vendor_the_paste
vendor_pattern
:.,+3s/^/vendor_/
另一个例子,我只需要在一个 125 行的块中添加两个空格,所以我使用了(光标位于块第一行的开头):
:.,+125s/^/ /
工作得很好。
如果需要对整个文件进行更改,
:1,$s/^/vendor_/
如果只需要更改几行,
转到需要更改的第一行,然后给出命令
:.,ns/^/vendor_/
将 n 替换为块中最后一行的行号。
或者,
:.,+ns/^/vendor_/
将 n 替换为需要更改的行数减 1。
j
或^L
。你应该看到 Vim 并不忙。它只是在等待。其次,尝试将'timeout'
更改为较低的值,例如80
(而不是默认的1000
)并观察它超时的速度更快。timeoutlen
而不是timeout
。A
而不是I
,它将在所选内容之后插入阻止而不是之前。但是,如果您的线条长度不同,那将行不通。我喜欢为此使用匹配每行末尾的替换,例如选择一些行并使用:s/$/inserted/
。