一、引言
*近在学习《Kafka 权威指南》的时候,在第二章安装 Kafka 的地方看到了关于 cat 的这么一种用法:

%title插图%num
乍一看这句 cat > file << EOF 的用法,我有些迷惑,但是能够肯定的是,我知道这句命令的作用是什么:

这是作者在安装 Zookeeper 过程中使用的命令,目的是在 /usr/local/zookeeper/conf 下创建一个配置文件 zoo.cfg,在 zoo.cfg 输入三行配置信息,并且手动输入 EOF 作为结束文件内容输入的结束标志。

作为 Linux 的菜鸟,我被这样的用法给深深的震撼了 T_T,接下来让我们仔细分析下这个看上去很简单的命令,来看看为什么它能够做到这一点。

二、探索
探索一条命令*好的方法,自然就是去尝试它,这也是 Python 设计 IDLE 的目的所在,那就让我们抛开复杂的理论,直接开始吧。

1. 尝试 cat > file
我们首先尝试去掉后面的 << EOF

# cat > file

然后发现它在新的一样闪现着光标,意味着可以输入内容,可以简单的输入一个 1

# cat > file
1

这里我们没法使用 EOF 作为文件结束标识,只能使用 Ctrl + C 或者 Ctrl + D 才能结束掉文件内容输入。此时我们看一看文件内容

# cat file
1

当然了,我们可以再尝试着对 file 文件进行一次 cat 写入操作,写入一个 2,然后 Ctrl + D

# cat > file
2
# cat file
2

由此,我们得知,cat > file 可以对 file 文件内容进行编辑,一旦 file 文件存在,则 file 原来的数据被新输入数据覆盖,并且在输入的时候,光标前方没有 > 提示符(cat > file << EOF 是有的),*后,标记输入文件完成的方式也只有使用 Ctrl + C 或者 Ctrl + D。

2. 尝试 << EOF
我们再来尝试下 << EOF 的作用

# << EOF
>

我们发现出现了新的一行,并且光标闪烁意味着可以输入内容,在光标前面还有 > 提示符,我们可以简单输入一个 1

# << EOF
> 1
>

接着,我们可以发现,Ctrl + C 和 Ctrl + D 可以暴力中断 << EOF 命令

# << EOF
> 1
> ^C
# << EOF
> 1
> -bash: warning: here-document at line 76 delimited by end-of-file (wanted `EOF’)

当然,看上去使用 EOF 作为结束是*合理的

# << EOF
> 1
> EOF

此时,我发现 << EOF 结束了也就结束了,内容去哪里了呢,我们试着用一个变量去接住它的值呢

# a=<<EOF
> 1
> EOF
# echo $a

 

惊奇而又伤心的是,我们发现 a 并没有像我们想象的那样输出 1,看来 << EOF 并非是一般的缓存信息。但是令人很开心的事情,仿佛我们又发现了一个新大陆,因为我把 EOF 输错了

# << EFO
> 1
> EOF
> EFO

哈哈,这真是一个有趣的事情,我把 EOF 输错为 EFO,结果结束判定字符串就变成了 EFO 而不是 EOF 了。

3. 将 cat > file 和 << EOF 合在一起
此时,再思考 cat > file 和 << EOF 合在一起的行为就不是那么难了。其中 cat > file 负责创建 file 文件,并提示用户输入文件内容,<< EOF 负责显示提示符 >,并且以 EOF 判定文件内容输入结束。

三、原理
尝试的过程是非常轻松惬意的,不过我还是更倾向去找一下权威的解释。

1. cat > file 背后的原理
根据我在网上的搜索,我发现 cat 命令的定义是这样的

cat 命令用于连接文件并打印到标准输出设备上。

而 > 在 linux 是意味着输出重定向的。简而言之,cat > file 就意味着

cat > file 用于创建文件并将标准输入设备上的内容输出重定向到 file 文件中去

2. << EOF 背后的原理
根据我在网上的搜索,得知

EOF是END Of File的缩写,表示自定义终止符.既然自定义,那么EOF就不是固定的,可以随意设置别名,在linux按ctrl-d就代表EOF.

果不其然,这个与我在上一步中的探索结果是一致的。

3. 扩展
我们既然说到了 > 意味着输出重定向,那么还可以使用 >> 来代表着追加内容而不是覆盖内容,同样的,<< EOF 和 > file 的位置也不是固定的,二者可以交换。

# cat > file << EOF
# cat << EOF > file
# cat >> file << EOF
# cat << EOF >> file

这里大家可以自行尝试,对于熟悉这个惯用法还是比较有用的 ^_^

四、总结
虽然这么简单的一个 cat > file << EOF 延伸出来讨论了这么多,好像看上去有些啰嗦了,但是我个人还是挺喜欢这种 发现->探索->原理 的模式去学习和记忆一些技能的。

总的来说,当你想要方便的往一个文件中写入多行内容,又想要同时能够在命令上中输入,并且自定义文件结束符的,就可以使用 cat > file << EOF 的模式来完成。