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
这样做的最佳方式是什么?
答案 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一遍又一遍地重播你的击键。将问题视为一组可重复的任务确实需要一些练习,但这并不是我们擅长做的事情:)