如何在Vim中使用外部命令来修改选定的单词和行?


22

我发现在其他编辑器中有用的是以下功能:

  • 选取所选文字
  • 运行一个外部命令并将选择传递给它 stdin
  • 接受外部命令stdout并用其替换当前选择。

这样,您可以编写有用的文本工具,使用可以执行基本io的任何语言对选择进行操作。

vim如何使用选择来完成?单个字符,单词,段落等

(直接在命令行中,还是通过键绑定?)


注意

之类的命令!sort在行级上工作,之所以问这个问题,是因为我想对选择进行操作。(即,如果x按下该文本将被删除)。

Answers:


17

我发现通常最简单的方法是使用可视模式v(或大写V选择整行),然后选择要传递的文本。

然后输入:

:!cat

这样,它没有任何用处。我经常使用的有用命令是:

:!python -m json.tool

格式化JSON。

您也可以键入(不使用可视模式):

:<range>!command

例如,对于整个文件:

:%!python -m json.tool

或对于当前行:

:.!python -m json.tool

与此配合使用的另一个真正有用的工具是sort命令。
Cody Poll

4
@CodyPoll Vim :sort怎么了?
马丁·图尔诺伊

5
@Carpetsmoker外部sort命令具有更多选项,并且(取决于语言环境等)产生不同的顺序。
derobert

1
这对于选择一行中的单个单词不起作用。(请参阅问题中提到的单词级别选择)
ideaman42'2

@ ideasman42对……我想我最初以“行词”而不是“行词”来阅读这个问题……在任何情况下,用单词来完成都是不明显的,UNIX程序可以在行上工作,而Vim也不例外。我做了一些实验,并找到了解决方案,但是效果不是很好。也许我的方法是错误的,所以我只待几天,然后再回头。
马丁·图尔诺伊

7

我写了一个名为express.vim的插件,可以帮助解决这个问题。该插件定义了一个运算符g=,使您可以评估运动(或视觉选择)上的VimScript表达式。它提示您输入一个表达式,您可以在其中v:val用作运动所覆盖的文本(或再次是“视觉选择”)的占位符。

在这种情况下,有用的表达式将使用system()运行外部命令的函数。

system('tr a-z A-Z', v:val)

(在这里,我用作tr一个简单的示例外部命令。)

针对这个问题使用express.vim的方式是在可视模式下选择文本,然后键入g=该表达式,然后点击Enter

g=system('tr a-z A-Z', v:val)<CR>

我承认,它不容易使用。(实际上,我自己很少使用此插件!)我正在考虑添加一种快捷方式来调用外部命令,例如使用开头表达式!。如果最终这样做,我会在这里发布更新。

编辑

我修改了express.vim,以将表达式开头!视为外部命令。因此,坚持使用tr示例,以上内容变得简单得多。视觉选择后,键入以下内容:

g=!tr a-z A-Z<CR>

说明:

  1. 调用快递运营商 g=
  2. 输入!tr a-z A-Z作为表达式
  3. Enter

4

您正在Vim中寻找过滤器命令。请参阅:help filter。以下是相关文档:

!{motion}{filter}   Filter {motion} text lines through the external
                    program {filter}.
!!{filter}          Filter [count] lines through the external program
                    {filter}.
{Visual}!{filter}   Filter the highlighted lines through the external
                    program {filter} (for {Visual} see |Visual-mode|).
                    {not in Vi}

:{range}![!]{filter} [!][arg]               *:range!*
                    Filter {range} lines through the external program
                   {filter}.  ...[See documentation for details]

因此,键入5!!sort将对从光标开始的接下来的5行进行排序。


是否可以过滤单个单词?(不是线路级别)
ideaman42 '16

是。第三个选项(可视模式)适用于突出显示的任何内容(单词,分行,多行,矩形块等)。
Sameer 2013年

1
第三个选项还可以过滤整行。如果您选择一个单词并对其进行过滤(例如,通过)tr [:lower:] [:upper],则vim不仅会修饰该单词,还会修饰整个行。
maria's

0

请注意,可以使用以下方法完成此操作:

  1. 直观地选择您想要的
  2. s^R=system('tr a-z A-Z', @")[:-2]^M(使用^RCTRL + R,并使用^ M进入)

它也可以与任何选择+替换的东西一起使用ci"^R=...


在多行文本选择上运行此命令时(在按下v并移动光标之后),我得到了错误E16: Invalid range\nE16: Invalid range\nE476: Invalid command(在Linux上tr以及存在其他基本命令)。
ideaman42

您按下s进入插入模式还是:s命令?
卢克·赫米特

不必怀疑,但也不确定您的意思,也许示例可以说明如何将其绑定到键?
ideaman42

您是直接s从视觉模式击中,还是:先击中?:我编写的键序列没有涉及。映射为:vnoremap µ s<c-r>=system('tr a-z A-Z', @")[:-2]<cr>
卢克·赫米特
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.