是否可以将vim命令传递到vim?


18

我要运行以下shell。

wea-this is the end of the second word | vim j
exit 0

我希望可以将击键w(向前移动一个单词),然后e(该单词的末尾),然后a(附加)然后-this is the end of the second word(文本)用管道传递到j已包含单词的Vim文档。

当我运行shell脚本时发生以下错误。

/root/bin/tt.sh: line 1: wea-this: command not found
Vim: Warning: Input is not from a terminal

我正在运行Ubuntu 14.04。两种类型的答案将不胜感激:

  1. 如何使用管道来达到这个理想的结果。
  2. 我可以使用“ Vim命令”(不是ed或sed命令)从Shell脚本编辑文本文档的另一种方法。

1
|字符管一个命令的输出到另一个。wea-this不是命令。管道也不能用于实现您想要的目的;这会使Vim的stdin成为左手应用程序,而不是键盘。如果要将stdin放入vim的缓冲区中,请以减号开头以指定文件名:echo Hello, world! | vim -
dash-tom-bang

Answers:


15

要将字符串插入"hello"文件的第一行j,可以在shell中键入以下命令:

vim +"1 | put! ='hello'" j

  • :1 将光标移动到缓冲区的第一行
  • :put! ='hello' 将字符串“ hello”粘贴到当前行上方

要插入字符串"hello",然后保存并退出文件:

vim +"1 | put! ='hello' | x" j

和以前一样,我们只是添加了:x保存并退出的Ex命令。

通常,您可以从交互式shell或bash脚本在文件上执行任何顺序的Ex命令,如下所示:

vim +'Ex command1 | Ex command2 | ...' file

如果您有很多Ex命令,则可以将它们全部写在一个专用文件(例如myExCommands.vim)中,每行一个命令,然后可以从Shell或脚本中获取它(使用Ex命令:source或简短版本):so) 像这样:

vim +'so myExCommands.vim' file

编辑

我们看到您已编辑问题。
我认为前面的答案仍然适用,因为您可以使用Ex命令:normal和从Ex模式执行任何常规命令:execute

例如,假设您要:

  • 将光标移到缓冲区的第一行(1G
  • 将光标移动到(_)行的第一个非空白字符
  • 将光标向前移动一个词(w
  • 将光标移到新单词(e)的末尾
  • 光标下方的字符(a)之后进入插入模式
  • 插入字符串 hello
  • 保存并退出(:x

为此,请j在外壳上输入:

vim +"execute 'normal! 1G_weahello' | x" j

有关更多信息,请参见:

:help +cmd
:help :normal
:help :execute

我未能完全阐明我的目标。我希望能够使用vims命令,例如w向前移动单词等。我将编辑问题以更正。
杰森·巴桑尼斯

@JasonBasanese我已经编辑了答案,可以执行Ex命令:normal:execute执行所需的操作吗?
saginaw 2015年

9

这是一种可以使用普通模式命令而不是仅ex命令来编辑从stdin提供给Vim的流的方法。这不是一个非常有用的示例,但是它说明了所涉及的技术。它假定您的外壳是bash。

echo "The brown fox jumped." | vim -s <(printf 'wcwred\e:wq! foo\n') -

-在年底告诉Vim阅读文本(而不是命令)从标准输入。该-s告诉Vim从指定的文件执行的按键。在这种情况下,该文件是bash进程替换的输出。在<(...)被命名管道的名称所取代。管道的输出是括号内命令的输出。在wcwred\e一个字将光标移动和变化,明年字red。将:wq! foo\n结果保存到文件foo即使该文件已经存在。最终结果是一个名为的文件,foo其中包含文本The red fox jumped.

有关这些主题的更多信息,请参见

:help -file
:help -s

另见Process Substitution一节的bash(1)手册页。


添加到我的〜/ .zshrc:中vimx () { vi -s <(echo "$1"':wq') "$2" &> /dev/null; }。现在可以了vimx 'iThe brow fox jumped.\e' foo; vimx 'wcwred\efjdwiclimbed\e' foo; cat foo。整齐!
伦纳德保利

4

我发现采用从子外壳重定向的程序输出的方法非常简单:

vim <( program )

例:

 vim <( grep -nH  hello  myFile.cpp )
 vim <( find . -name '*.cpp' -exec grep -nH code_expr {} \+ )

4

我和您有同样的愿望:我想编写普通的vim命令并让它们编辑管道流。我对默认vim选项提供的以这种方式使用普通vim的困难(这么多标志!)感到失望。

因此,我在vim上写了一个小的包装来做到这一点:https : //github.com/MilesCranmer/vim-stream/。叫做vims

包装程序的核心是以下命令:

vim - -nes "${vim_cmds[@]}" -c ':q!' | tail -n +2

使用此命令,通过我执行的命令生成,它非常简洁,并且由于vim是模式编辑器,因此我制作vims了模式流编辑器。有三种主要模式可用于管道编辑思维方式:

[-t|--turn-off-mode] - (Default mode)
                       Every string is a vim command line, e.g., '%g/foo/d' deletes
                       all lines with foo.
[-e|--exe-mode] -      Translated to '%g/$1/exe "norm $2"', see examples below
[-s|--simple-mode] -   Like exe-mode, but runs on 1st line only

看这个:

$ echo "Hello World" | vims -s "ea Beautiful"
Hello Beautiful World

因此,e转到的末尾Hello,然后a开始追加。

在exe模式下,有些幻想者注释掉包含的行my_bad_var,并删除前一行。

cat my_script.cpp | vims -e 'my_bad_var' 'I//\<esc>kdd'

转换为vims '%g/my_bad_var/exe "norm I//\<esc>kdd"'- I是在行首开始插入的命令,并且//是注释序列。 \<esc>kdd按下退出键,向上移动一行,然后删除该行。

我在仓库中总共有11个示例,我建议您检查一下。同样,这是在vim之上运行的,这只是使vim更像sed进行流输入的一种方法(但保留了所有您钟爱的vim宏!)


3

这是一个相当老的问题,但是我觉得值得一提的是,如果您给定的发行版/ OS可以访问moreutils,那么您可以安装它,并简单地vipe用作标准添加vim

echo foo | vipe # Now you can edit "foo" to be "bar"!

moreutils对于其他工具也非常方便,如果您是认真的命令行用户,我强烈建议您使用它们!:)查看作者的简介(上一个链接)以了解更多详细信息。

moreutils应该可以通过软件包管理器和Mac上的Homebrew对大多数* nix发行版普遍可用。例如...

# Arch Linux and MSYS2 (more below) as part of the `community` repo
pacman -Sy moreutils


# Mac OS and Homebrew
brew install moreutils

moreutils也是MSYS2软件包存储库一部分,因此您也可以从技术上在Windows上使用它。:)

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.