我想用选择的结果通过管道传递到命令中来替换一行的一部分。
例如:
echo "hello $(echo "world" | base64)" | vim -
这将打开其中包含hello d29ybGQK
的缓冲区。现在按wvw
以可视方式选择d29ybGQK
。
然后,我尝试:!base64 -d
,并且希望缓冲区包含hello world
,但没有发生。确实,整行都通过管道传递到命令中,并且替换了整行。
是否可以仅替换视觉选择,并且仅将该选择通过管道传递到命令中?
我也尝试了c<c-r>=system('base64 -d')
,但是没有将视觉选择发送到命令的标准输入。
答案 0 :(得分:4)
使用!
进行过滤始终是逐行的。您使用c
和
表达式寄存器是解决此问题的绝佳方法。你才忘了
将输入传递给system()
,这是它的第二个可选参数。
由于您刚刚更改了所选文本,因此它进入了"
寄存器
自动。您需要做的就是将其取回并传递给
getreg()
的系统:
c<C-R>=system('base64 -D', getreg('"'))
请注意,base64
可能在末尾添加换行符。如果要删除
可以将整个内容包装在trim()
中,这是Vim 8中的新功能,或者
使用[:-2]
:
c<C-R>=trim(system('base64 -D', getreg('"')))
c<C-R>=system('base64 -D', getreg('"'))[:-2]
这是[0:-2]
的简写,意味着从角色那里抢走一切
从0到倒数第二个字符串。
如果经常使用,请考虑创建视觉地图:
vnoremap <leader>d c<C-R>=system('base64 -D', getreg('"'))[:-2]<CR>
答案 1 :(得分:1)
出于历史原因, Ex命令本质上是基于行的。尊敬的 vi 还没有可视模式。该限制包括使用:range!
通过外部命令进行过滤;它将始终过滤整行。
对于像您的示例这样的简单输入,临时拆分行,过滤然后重新组装可能是最简单的。例如:
:substitute/ /\r/ | execute '.!base64 -d' | -1join
对于通用解决方案,您需要使用或实现一个插件,该插件可抓取所选文本,对其进行过滤(可能通过system()
进行过滤),然后用结果替换所选内容。
我的SubstituteExpression plugin有一个{Visual}g=
映射,可以映射Vimscript表达式,Vim函数和命令以及外部命令。
express.vim提供了几乎相同的实现。它还允许通过:MapExpress
和:MapSubpress
动态创建运算符,而我将使用TextTransform plugin来创建运算符,无论如何,您都需要将其安装为依赖项。我的插件提供了更高级的(跨模式)重复和:Ex
-命令表达式变体,但您还需要安装两个大的依赖项。