执行VIM中多行的命令

时间:2011-07-20 13:12:36

标签: shell vim scripting

VIM的一个常用功能是通过外部命令过滤文件(或选择的文本),并将选择替换为结果,例如:

:'<,>'!sort

所以

c
b
a

将被排序并将导致

a
b
c

也可以用外部命令的返回值替换当前行,例如:

:,!ls | wc -l

将在当前目录中插入文件数(在我的情况下,例如:)

41

但是有没有办法将字符串传递给shell的命令?例如,这可能是我视觉选择的内容:

line_x
line_y
line_z

我需要的是执行一些shell命令并将每个选定的行作为一个shell脚本参数,例如:

my_bash_command line_x -c -e -f
my_bash_command line_y -c -e -f
my_bash_command line_z -c -e -f

这样做的最佳方式是什么?

3 个答案:

答案 0 :(得分:10)

我建议您使用xargs -L1

示例:

:%!xargs -L1 wc -l

基本上xargs [cmd]将使用多行参数运行以下[cmd]。但是使用-L1参数,[cmd]将为每一行执行命令。

如果需要为命令的参数提供特定顺序,可以使用xargs的{​​{1}}选项提供要由参数列表替换的模式。

示例:

-I

如果您觉得非常喜欢冒险,您可以直接执行代码:

:%!xargs -L1 -I {} rake {} --trace

答案 1 :(得分:2)

echo map(getline("'<", "'>"), 'system(v:val)[:-2]')

:h map()
:h system()
" [:-2] ~> chomp

如果您愿意(:echo:put等),可以使用行插入功能代替setline()

答案 2 :(得分:1)

宏可能是最简单的方法。将光标放在第一行的开头,并将自己记录到一行。然后你可以在很多行上运行宏。例如,这会将arg传递给echo并将结果替换为带参数的行。用光标在命令的第一行某处键入这些。

qa0y$:r!echo <C-r>"<Enter>kddjq

此行将一个宏记录到寄存器a(qa)中,移动到行的开头(0),复制整行(y $),进入命令行模式(:),从运行中读取结果一个命令进入你下面的行(r!echo ....),然后是Cr,然后“将你的文本粘贴到:r命令,k将你移回原来的行,dd删除了行,j将你移动到了下一行(应该包含你的下一个命令),然后停止录制(q)。

现在你可以通过按@a(在执行一次@@重复最后一次运行宏之后)或通过按下想要运行宏5 @ a的次数来在每一行上运行宏。或者甚至更好地突出线条和按压:规范! @a

键入时看起来很多,但是当你习惯了宏时,它们可以节省时间。你基本上做你想要的第一行,然后让vim一遍又一遍地重播你的击键。将问题视为一组可重复的任务确实需要一些练习,但这并不是我们擅长做的事情:)