ChatGPT解决这个技术问题 Extra ChatGPT

Vim:在多行中插入相同的字符

vim

有时我想跨多行编辑某个视觉文本块。

例如,我会采用如下所示的文本:

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/^/vendor_/”
感谢您的回复。如果我只想在每一行附加一个单词,那就行了。但是我使用的方法可以在任何位置进行。让我用一个更复杂的例子来添加另一个我的例子。
然后使用 shift-V 突出显示要更改的行,并键入适当的搜索和替换命令 - 在第二个示例中,:s/models\./\0whatever./
实现上述的方法很多。要完全回答问题的所有部分,然后是第 1 部分)我编辑的正则表达式或可视模式 esc 与答案中提供的一样工作得很好(我更喜欢 GVIM 中的可视选择)。对于第 2 部分),宏可能是 Brian Neal 提供的最简单的方法。我所知道的所有这些“操作方法”的最佳资源是 Drew Neil 的 Practical Vim。每当您忘记公式时,都是出色的快速阅读和轻量级参考。希望这个建议对某人有所帮助,对于许多 vim 用户来说,这将是非常值得的。
@Paul:如果您是 counting keystrokes,则可以将 \0 替换为 &

A
Antonio

将光标移动到名称中的 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


我无法让它在 Windows 中工作(因为 CTRL+V 已映射为剪贴板粘贴)。但对于 Windows 版本,Vim 也将其映射到 Ctrl+Q。
@Ven:Vim 在那段时间里实际上并不忙——它只是在等你按另一个键,最终超时。为您提供两个实验:首先,尝试按 Escape,然后立即按另一个键,例如 j^L。你应该看到 Vim 并不忙。它只是在等待。其次,尝试将 'timeout' 更改为较低的值,例如 80(而不是默认的 1000)并观察它超时的速度更快。
@icktoofay 看起来您要设置的变量是 timeoutlen 而不是 timeout
@ANjaNA:如果您要插入的位置都在同一列中(例如,如果数字都是相同的长度),您可以使用相同的技术,除了按 A 而不是 I,它将在所选内容之后插入阻止而不是之前。但是,如果您的线条长度不同,那将行不通。我喜欢为此使用匹配每行末尾的替换,例如选择一些行并使用 :s/$/inserted/
按 esc 后我必须按向下箭头才能使其正常工作
A
Alex Spurling

另一种方法是将 . (dot) 命令与 i 结合使用。

将光标移动到您想要开始的位置 按 i 键入您想要的前缀(例如 vendor_) 按 esc。按 j 下一行 Type 。重复上一次编辑,再次自动插入前缀 在 j 和 . 之间快速交替。

我发现这种技术对于少量添加通常比可视块模式更快,并且具有额外的好处,如果您不需要在范围内的每一行上插入文本,您可以通过按额外的 j 轻松跳过它们。

请注意,对于大量连续添加,块方法或宏可能会更好。


很高兴看到另一种方法。
我只喜欢这几行。更容易执行 IMO。
输入您想要的前缀后,您是否不需要按转义键?
@iamnotsam,如果您处于插入模式,那么是的,您需要在移至下一行之前按 Esc。否则按“。”将简单地插入一个句点。
L
Loukan ElKadi

使用 CtrlV 选择要修改的行。按: I:在所选内容之前插入。 A:在选择的内容之后追加。 c:替换选择的内容。键入新文本。按 Esc 将更改应用到所有选定的行。


出色的!我只想强调像我这样的 VIM 新手的最后一步 Esc - 我花了一段时间才弄清楚这些更改会“稍后”传播!
很好,也不知道“A”和“C”选项。
为什么这对 v 不起作用?我可以用 Ctrl+V --> A 做到这一点,但是用 v 来选择文本不起作用—— A 只附加到该行。不是都选吗?另外,很奇怪——如果我将视觉块延伸到行尾,A 只会附加到行尾;否则它会附加到每一行的可视块结束的任何地方。就像它无法识别 aA 之间的区别。
我需要使用 c 而不是 C,但效果非常好。谢谢
P
Peter Mortensen

我会使用宏来记录我的动作,然后重复它。

将光标放在名称的第一个字母上。点击 qq 开始记录到 q 缓冲区。按 i 进入插入模式,键入 vector_,然后按 Esc 退出插入模式。现在点击 0 回到行首。现在按 j 下去。现在再次按 q 停止录制。

你现在有一个不错的宏。

键入 3@q 以执行您的宏 3 次以执行其余的行。


“q”是特殊的(对于“快速宏”吗?)?
如何使宏持久化(跨多个会话工作)?
@PeterMortensen Vim 有一个称为会话的功能,它将持久保存您可以查看的缓冲区(以及许多其他内容)。
从一个彼得到另一个,很好的答案!
s
srini.venigalla
:%s/^/vendor_/

还是我错过了什么?


您错过了这样一个事实,即它可能是文件中的潜文本,其中包含不需要 vender_ 前缀的许多其他行。
@dan 如果只需要一个潜台词,您可以将搜索限制为一组行号,例如 1,4s/^/vendor_/
@BradKoch 有趣。我不知道行号限制,谢谢。
这很有趣,但更实用的是用 V 直观地阻止选择并输入 :。它将在 ed 表达式前面加上 :'<,'>,这使得 ed 仅适用于带有 :'<,'>s/^/vendor_/ 的选择
如果您像我一样突出显示匹配项,您可能需要在之后运行 :noh
a
arcseldon

2016 年 1 月更新

虽然接受的答案是一个很好的解决方案,但实际上击键次数略少,并且可以更好地扩展 - 原则上基于接受的答案。

将光标移动到名称中的 n。进入可视块模式 (ctrlv)。按 3j 按 I。输入 vendor_。按 ESC。

https://i.stack.imgur.com/ce8e1.gif

请注意,这比提供的接受答案的击键次数更少(比较第 3 步)。我们只计算要执行的 j 个动作的数量。

如果您启用了行号(如上图所示),并且知道您希望移动到的行号,则可以将步骤 3 更改为 #G,其中 # 是所需的行号。

在我们上面的示例中,这将是 4G。然而,当只处理几个行号时,显式计数效果很好。


A
Aubrey Lavigne

可以更灵活的替代方案:

示例:在行首输入文本 XYZ

:%norm IXYZ

这里发生了什么事?

% == 在每一行执行

norm == 在普通模式下执行以下键

== 在行首插入

XYZ == 你要输入的文字

然后你按 Enter 键,它就会执行。

具体到您的要求:

:%norm Ivendor_

您还可以选择特定范围:

:2,4norm Ivendor_

或在选定的可视范围内执行:

:'<,'>norm Ivendor_

或为匹配“目标”正则表达式的每一行执行:

:%g/target/norm Ivendor_

是否可以在插入模式(规范 Iabc)下发送像 这样的键序列来做更多有趣的事情?
@batbrat 我刚刚想通了!您可以点击 ctrl-v ctrl-[ 插入“转义 Esc”,这会将您拉回“正常模式”以执行正常命令。我刚刚用 '<,'>norm Iaa^[ysiw" 对此进行了测试,其中 ^[ 是转义的 Esc。
:%mode 方法非常值得了解。我很高兴我偶然发现了这个答案!
c
computingfreak

我想在只有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


这对我来说是完美的解决方案,因为我经常只使用 vim-tiny。
P
Peter Mortensen

您可能还有一个用例,您想删除一段文本并替换它。

像这样

Hello World

Hello World

Hello Cool

Hello Cool

您可以在两行中仅视觉块选择“世界”。

键入 c 进行更改 - 现在您将处于插入模式。

插入你想要的东西并点击逃生。

两者都会垂直反射。它就像“I”一样工作,只是它用新文本替换块而不是插入它。


P
Peter Mortensen

假设你有这个文件:

something

name
comment
phone
email

something else
and more ...

您想在“name”、“comment”、“phone”和“email”前面添加“vendor_”,无论它们出现在文件中的什么位置。

:%s/\<\(name\|comment\|phone\|email\)\>/vendor_\1/gc

c 标志将提示您进行确认。如果你不想要提示,你可以放弃它。


A
Arpan Saini
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

此方法是否适用于所有版本的 vim 或需要任何 vim 插件?我问的原因是 b/c 它有时可以在某些机器上工作,但有时不能。我不知道有什么区别。 Windows 上 git 附带的 vim - 我无法让它工作。在一些 ubuntu 和 centos linux 机器上,我无法让它工作。我在一些罕见的情况下取得了成功,但我无法重现成功。这是一个谜。按下 ESC 后似乎什么也没有发生。
奇怪的是,它现在对我有用。没有任何改变,除了星星 :) 在寻找我的问题的解决方案时,我确实在这个页面上找到了一些东西,尽管它提到了在 vim 中寻找的东西 vim.wikia.com/wiki/Inserting_text_in_multiple_lines 在 Vim 中,检查你是否有块运算符功能( I、A 等)通过输入 :version 命令。输出应包括 +visualextra。
我的意思是总体上添加评论,而不是您的答案。这些答案中的大多数都说了同样的话,但使用了不同的词。我的提供了一些不同的东西,并包含了一个链接。
P
Peter Mortensen

Ctrl + v 进入可视块模式 使用向上和向下箭头选择行 输入小写 3i(按小写字母 I 三次) I(按大写 I。这将带您进入插入模式。)写下您要添加的文本Esc 按向下箭头


V
Victor

我来这里是为了在多行中粘贴一个已经复制的字符串。当使用 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

M
Mike P.

:.,+3s/^/vendor_/

另一个例子,我只需要在一个 125 行的块中添加两个空格,所以我使用了(光标位于块第一行的开头):

:.,+125s/^/ /

工作得很好。


k
kjohri

如果需要对整个文件进行更改,

:1,$s/^/vendor_/

如果只需要更改几行,

转到需要更改的第一行,然后给出命令

:.,ns/^/vendor_/

将 n 替换为块中最后一行的行号。

或者,

:.,+ns/^/vendor_/

将 n 替换为需要更改的行数减 1。