如何从命令提示符运行一系列 vim 命令

Posted

技术标签:

【中文标题】如何从命令提示符运行一系列 vim 命令【英文标题】:How to run a series of vim commands from command prompt 【发布时间】:2014-06-07 17:51:19 【问题描述】:

我有四个文本文件 A.txt、B.txt、C.txt 和 D.txt 我必须在所有这些文件中执行一系列 vim 编辑。 目前我正在做的是打开每个文件并一个一个地执行相同的vim命令。

是否可以制作一个我可以从命令提示符运行的脚本文件,这意味着无需打开实际文件进行 vim 编辑。

例如,如果我必须在 vim 编辑器中打开 A.txt 文件后执行以下 vim 命令:

:g/^\s*$/d
:%s/^/[/
:%s/\(.*\)\(\s\+\)\(.*\)/\3\2\1
:%s/$/]/
:%s/design/test/

是否可以制作一个脚本文件并放置所有这些命令,包括gvim A.txt(文件中的第一个命令)。 并编辑从命令提示符运行脚本文件。

如果可能,请告诉我如何操作以及如何一次处理单个或多个文件?

【问题讨论】:

【参考方案1】:
vim -c <command> Execute <command> after loading the first file

按照你的描述做,但你必须一次做一个文件。

所以,在 Windows 外壳中...

for %a in (A,B,C,D) do vim -c ":g/^\s*$/d" -c "<another command>" %a.txt

POSIX shell 类似,但目前我面前没有机器。

我想您可以一次加载所有文件并执行此操作,但这需要为每个文件重复 vim 命令行上的命令,类似于

vim -c "<command>" -c "<command>" -c ":n" (repeat the previous -c commands for each file.)  <filenames go here>

编辑:2014 年 6 月 8 日: 仅供参考,我在几分钟前发现了这一点。

vim 有命令 bufdo 对编辑器中加载的每个缓冲区(文件)执行操作。查看 bufdo 命令的文档。在 vim 中,:help bufdo

【讨论】:

vim -c "" -c "" -c ":n" (对每个文件重复前面的 -c 命令。) 这就是我非常感谢... 最后别忘了-c ":wq"【参考方案2】:

在命令行中直接传递给 Vim 的 -c 命令数量限制为 10 个,这不是很可读。或者,您可以将命令放入单独的脚本中并将其传递给 Vim。方法如下:

静默批处理模式

对于非常简单的文本处理(即像增强的 'sed' 或 'awk' 一样使用 Vim,也许只是受益于 :substitute 命令中增强的正则表达式),请使用 Ex-mode .

REM Windows
call vim -N -u NONE -n -es -S "commands.ex" "filespec"

注意:静默批处理模式 (:help -s-ex) 会弄乱 Windows 控制台,因此您可能需要在 Vim 运行后执行cls 来清理。

# Unix
vim -T dumb --noplugin -n -es -S "commands.ex" "filespec"

注意:如果"commands.ex" 文件不存在,Vim 将挂起等待输入;最好事先检查它的存在!或者,Vim 可以从标准输入读取命令。如果您使用 - 参数,您还可以使用从标准输入读取的文本填充新缓冲区,并从标准错误读取命令。

全自动化

对于涉及多个窗口的更高级处理,以及 Vim 的真正自动化(您可能与用户交互或让 Vim 运行以让用户接管),请使用:

vim -N -u NONE -n -c "set nomore" -S "commands.vim" "filespec"

这里是使用的参数的摘要:

-T dumb           Avoids errors in case the terminal detection goes wrong.
-N -u NONE        Do not load vimrc and plugins, alternatively:
--noplugin        Do not load plugins.
-n                No swapfile.
-es               Ex mode + silent batch mode -s-ex
                Attention: Must be given in that order!
-S ...            Source script.
-c 'set nomore'   Suppress the more-prompt when the screen is filled
                with messages or output to avoid blocking.

【讨论】:

很好解释。是否有任何开关可以将输出写入文件。我试过 -w, -W, :w 但没有帮助。 @EashwarGadanchi:通常情况下,您会将内容 :write 写入输入文件或不同的文件名,因此 Vim 充当过滤器,就像高级的 sedawk .在静默批处理模式下(所谓的“完全自动化”,您还可以使用:print 输出单个行,使用:verbose echomsg &lt;MSG&gt; 输出任意文本;这些将打印到标准输出(您可以将其重定向到文件中) . 为什么用--no-plugin 代替-u NONE?对于 Unix,您似乎可以从 -N -u NONE -n -es -T dumb 开始。我不确定这些都添加了什么。不是他们做什么,而是他们是否有所作为。好吧,他们中的一些人很可能会这样做。顺便说一句,不清楚哪个部分必须按特定顺序给出。哦,只有-es @x-yuri:最后我提到两者都可以使用;这取决于用例。 -u NONE 完全独立于用户设置,--no-plugin 避免了耗时的插件加载,但保留了用户的主要设置(因为开箱即用的默认设置不是很友好)。如果您确实需要插件,也可以省略两者,但这与您的配置最耦合。【参考方案3】:

您想对保存在脚本中的每个文件执行所有命令,比如“script.vim”,您可以像这样在一个文件上执行该脚本(正如其他人提到的那样):

vim -c "source script.vim" A.txt

更进一步,您可以将文件保存在脚本的末尾,方法是在脚本本身中添加 :w 命令,或者从命令行传递它:

vim -c "source script.vim | w" A.txt

现在,您可以使用 argdo 命令在 Vim 中对多个文件运行任何命令。所以你的命令变成了:

vim -c "argdo source script.vim | w" A.txt B.txt C.txt D.txt

最后,如果你想在对每个文件运行脚本后退出 Vim,只需添加另一个退出命令:

vim -c "argdo source script.vim | w" -c "qa" A.txt B.txt C.txt D.txt

【讨论】:

【参考方案4】:

试试下面的语法:

ex foo.txt <<-EOF
  g/^\s*$/d
  %s/^/[/
  %s/\(.*\)\(\s\+\)\(.*\)/\3\2\1
  %s/$/]/
  %s/design/test/
  wq " Update changes and quit.
EOF

ex 命令等同于vim -E。为详细输出添加-V1

另一种单行语法例如:

ex +"g/^\s*$/d" +"%s/^/[/" +"%s/design/test/" -cwq foo.txt

要从文件中加载命令,请使用-s cmds.vim

您也可以使用shebang for Vim to parse the file from the argument。

更多示例,请参见:

How to edit files non-interactively (e.g. in pipeline)? BashFAQ/021

【讨论】:

【参考方案5】:

JimR 和 Ingo 为您的用例提供了出色的答案。

不过,您可以使用我的 vimrunner 插件在 ruby​​ 中编写交互脚本:https://github.com/AndrewRadev/vimrunner。

例子:

vim = Vimrunner.start

vim.edit "file.txt"
vim.insert "Hello"
vim.write

vim.kill

这对于更复杂的交互很有用,因为您可以获得编程语言的全部功能。

【讨论】:

以上是关于如何从命令提示符运行一系列 vim 命令的主要内容,如果未能解决你的问题,请参考以下文章

在 Windows 上如何使用 Vim 中开发者命令提示符的命令行?

如何从 VB.NET 运行 DOS/CMD/命令提示符命令?

您如何用Java编写命令提示符?

如何从 Visual Studio 命令提示符以外的命令行运行 regasm.exe?

如何以不同用户和管理员身份从命令提示符运行程序 [关闭]

如何从命令提示符检查 ZooKeeper 是不是正在运行或启动?