如何在 shell 脚本中使用 vi 命令?

How can I use vi command in shell script?

我使用的是 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、到sed、到awk、到ed。不过,我假设您有充分的理由想要使用 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引入插入模式。

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

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

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

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

echo "hihi" > test.txt

如果你真的想做一些更复杂的事情,post一些更多的细节。

从 bash 调用 vim:

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

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

vi 是历史上旧编辑器 exvisual 模式,是旧编辑器 ed 的扩展版本。您始终可以使用 exvi -e.

恢复到旧的线路模式

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

这里是

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

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

使用 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

编码愉快!


P.S。 在您使用的情况下:

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