我想以非交互方式使用vim编辑在管道输入中传递的文件,或就地编辑文件(类似于sed)。
$ sed -i'.bak' s/foo/test/g file   # Edit file in-place.
$ cat file | sed s/foo/test/g      # Parse file in pipeline.


但是我在这里可以读到以下内容:


sed是Stream EDitor,不是文件编辑器。但是,各地的人们都倾向于滥用它来尝试编辑文件。它不会编辑文件。


其次,一些选项是可移植的,例如就地编辑(sed)是可移植的。 vim?

评论

我认为您可以从第二个命令行中删除第二个文件。

@joeytwiddle完成。

#1 楼

要使用exviex的可视模式)非交互地编辑文件,可以使用+{command}-c {command}参数,这些参数允许您在读取第一个文件后执行vi命令。

ex是标准的命令行编辑器(类似于ed)。

还应该使用vipe(Vim命令行编辑器),它是moreutils软件包的一部分,它将允许您运行在Unix管道中间的编辑器中,并编辑在程序之间通过管道传递的数据。 :

$ ex -sc'%p|q!' <(echo Example)
$ echo Example | ex -sc'%p|q!' /dev/stdin


以下是替换后如何打印文件的简单示例:

$ ex /etc/hosts +%s/127/128/ge -sc'%p|q!'


更多示例就地编辑文件:

$ ex +'%s/127/128/g' -cswq file
$ ex -sc '%s/olddomain\.com/newdomain.com/g|x' file
$ printf '%s\n' 'g/olddomain\.com/s//newdomain.com/g' w q | ex -s file
$ ex -s "$file" <<< $'g/old/s//new/g\nw\nq'
$ ex -sc 'argdo %s/old/new/ge|x' ./**
$ find . -type f -exec ex -sc '%s/old/new/g|x' {} \;


还可以使用-s {scriptin}以便从文件中加载命令,例如:

$ printf "%s\n" '%s/foo/test/ge' 'wq' > cmds.vim
$ vim -s cmds.vim -es file

或使用I / O重定向:

$ vim file < cmds.vim


要编辑一个文件并将更改保存到另一个文件,请检查以下示例:

$ ex +%s/127/128/g -sc'wq! new_file' /etc/hosts
$ cat /etc/hosts /etc/fstab | vim - -es '+:%s/foo/test/g' '+:wq! file3'



更多实际示例。

RPM规范中的真实示例:

vim -E -s Makefile <<-EOF
   :%substitute/CFLAGS = -g$/CFLAGS =-fPIC -DPIC -g/
   :%substitute/CFLAGS =$/CFLAGS =-fPIC -DPIC/
   :%substitute/ADAFLAGS =$/ADAFLAGS =-fPIC -DPIC/
   :update
   :quit
EOF


>提取html标签:

ex -s +'bufdo!/<div.*id=.the_div_id/norm nvatdggdG"2p' +'bufdo!%p' -cqa! *.html


删除XML标签:

ex -s +'%s/<[^>].\{-}>//ge' +%p +q! file.txt


从标题和样式中删除样式标签打印已解析的输出:

curl -s http://example.com/ | ex -s +'/<style.*/norm nvatd' +%p -cq! /dev/stdin


使用多个复杂规则解析html:

ex -V1 $PAGE <<-EOF
  " Correcting missing protocol, see: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2359 "
  %s,'//,'http://,ge
  %s,"//,"http://,ge
  " Correcting relative paths, see: https://github.com/wkhtmltopdf/wkhtmltopdf/issues/2359 "
  %s,[^,]\zs'/\ze[^>],'http://www.example.com/,ge
  %s,[^,]\zs"/\ze[^>],"http://www.example.com/,ge
  " Remove the margin on the left of the main block. "
  %s/id="doc_container"/id="doc_container" style="min-width:0px;margin-left : 0px;"/g
  %s/<div class="outer_page/<div style="margin: 0px;" class="outer_page/g
  " Remove useless html elements. "
  /<div.*id="global_header"/norm nvatd
  wq " Update changes and quit.
EOF


还有更多示例:


如何在变量,流,文件或目录中的所有文件中用另一个字符串替换字符串?

什么是EX模式用于批处理?在超级用户SE上


另请参见:



将制表符转换为目录的每个文件中的空格?在SO

以递归方式删除所有文件中的尾随空格?在SO

如何从命令行将整个缓冲区写入标准输出?在Vim SE中

是否可以在非交互模式下执行VIM脚本?在unix SE上

将Vim缓冲区插入SO处的stdout

在SO处将缓冲区内容写入stdout。要有条件地删除html标记的内部内容?



评论


这是一个UUOC;只需使用vim'+:0,$ s / foo / test / g''+:wq! file2'file1代替。

–门把手
15年2月14日在12:49

请注意,至少其中一些示例不兼容POSIX,例如bufdo。尽管Vim几乎安装在各处,但值得一提的是,您只能使用ex的POSIX兼容功能来编写文件脚本。

–通配符
16年1月7日在9:19



这个问题和答案是什么促使我前瞻性学习并真正学习它的。谢谢。关于这个主题的进一步阅读(完整披露:我写了这些;)是:用ex反转每四行,并使用-c选项。如果需要,可以将它们添加到底部的链接列表中。 :)

–通配符
16年3月3日在20:03