【问题标题】:How can I use vi command in shell script?如何在 shell 脚本中使用 vi 命令?
【发布时间】:2016-10-01 17:04:21
【问题描述】:

我使用的是 CentOS 6.7

我想通过 vi 打开 test.txt 并插入文本“hihi” 然后保存并退出 vi。

#! /bin/bash

vi test.txt << 'END'
i
hihi
press ESC
w
q
END

这样的结果

Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: preserving files...
Vim: Finished.

我该如何解决?

【问题讨论】:

  • 我建议您的用例的解决方法是在附加模式下使用 cat 命令
  • 使用vi 有什么意义?

标签: shell vi


【解决方案1】:

在 shell 中使用 vi 命令可以这样工作:

vi -c "set fileformat=unix | wq" filename.txt

但是,这不适用于 g 等命令。

您需要使用两个 -c 参数才能使其工作,例如:

vi -c g/^/m0 -c wq filename.txt

vi filename.txt -c g/^/m0 -c wq

编码愉快!


附注 在您使用的情况下:

vi test.txt +$'i\nhihi' +wq

这将在内存中的当前行之前插入!

例如,如果您之前使用此命令在第 20 行之前插入了“hihi”:

vi test.txt +20$'i\nhihi' +wq     (insert hihi before line 20)

vi test.txt +20$'a\nhihi' +wq     (insert hihi after line 20)

然后在没有指定数字的情况下键入将使用内存中的最后一个数字。

vi test.txt +$'i\nhihi' +wq     (This command will now insert before line 20)

vi test.txt +$'a\nhihi' +wq     (This command will now insert after line 20)

您必须通过指定新编号来重置内存中的行号:

vi test.txt +0$'i\nhihi' +wq          (add hihi before line 0 to very top)
vi test.txt +0$'a\nhihi' +wq          (add hihi after line 0 to very top)
vi test.txt +1$'i\nhihi' +wq          (add hihi before line 1 to very top)
vi test.txt +1$'a\nhihi' +wq          (add hihi after line 1 as line 2)

如果不知道 test.txt 中的最后一行数,则可以使用 wc 计算行数。

(在最后一行之前添加 hihi)

vi test.txt +$(wc -l < test.txt)$'i\nhihi' +wq

(在最后一行后添加 hihi)

vi test.txt +$(wc -l < test.txt)$'a\nhihi' +wq

 


【讨论】:

    【解决方案2】:

    vi 历史上是旧编辑器ex可视 模式,是旧编辑器ed 的扩展版本。您可以随时使用exvi -e 恢复到旧线路模式。

    这样,它只是从标准输入中读取,因此可以很容易地在 bash 脚本中使用。

    原来是这样

    ex test.txt << END
    i
    hihi
    .
    wq
    END
    

    (点用于退出行模式下的输入模式,如ed

    【讨论】:

      【解决方案3】:

      从 bash 调用 vim:

      vim test.txt +$'i\nhihi' +w +q
      

      您可能还想查看“ed”。那是一个与 vi 有类似命令的编辑器,但它实际上是为从脚本调用而设计的。

      【讨论】:

      【解决方案4】:

      创建或修改文本文件的方法有很多,从catsedawked。不过,我假设您有充分的理由想要使用vi

      试试这个命令:

      echo $'ihihi\E:x\n' | vi test.txt
      

      实际操作如下:

      $ echo $'ihihi\E:x\n' | vi test.txt
      Vim: Warning: Input is not from a terminal
      $ cat test.txt
      hihi
      

      我发现这种方法很脆弱:如果vi 遇到错误情况,将不会看到任何消息。

      工作原理

      我们需要得到vi 才能看到转义字符。有很多方法可以做到这一点。我选择使用 bash 的 $'...' 字符串,因为它允许将转义输入为简单的两个字符串:\E。我们使用的步骤是:

      1. i 引入 insert 模式。

      2. 四个字符hihi被输入到缓冲区中。

      3. Escape,\E,退出插入模式。

      4. :x\n 退出并保存。

      【讨论】:

      • 感谢您的回复!
      【解决方案5】:

      你不需要为这么简单的事情使用 vi。您可以使用echo。例如:

      echo "hihi" > test.txt
      

      如果您真的想做更复杂的事情,请发布更多详细信息。

      【讨论】:

      • 感谢您的回复!