技巧:用 cat 合并文件

在我们有关 GNU 文本实用程序的连续系列中,Jacek Artymiak 对 cat 做了一下研究 — cat 这个命令是 UNIX 爱好者所热爱的,也是厌恶 UNIX 的人所憎恶的。

您常常需要将几个文件处理成一个文件并将这种处理的结果保存到一个单独的输出文件。cat(“concatenate”的缩写)命令在其输入上接受一个或多个文件并将它们作为一个单独的文件打印到它的输出。例如,cat chapter01 chapter02 chapter03 > book 将三个 chapterXX 文件保存在一个单独的 book 文件中。

输入文件按照它们在 cat 命令后的排列顺序被打印,因此,要调换信息的顺序,就必须先调换输入文件的顺序。此外,当需要处理的文件数目对于您来说过大而无法手工输入这些文件的名称时,您可以使用通配符,如在 cat chapter* > book 中使用的那样,记住,文件名将会按升序排列。当您突然发现 chapter13 被发送到输出中时会在 chapter2 之前,而会在 chapter02 之后时,这会引起很有意思的问题。

当 cat 的输出没有被重定向到一个文件或另一个命令的标准输出时,cat 表现出来的行为与多数命令行工具一样,即将其输出发送到控制台。这意味着您可以使用 cat 来显示文件;例如,您可以使用 cat /etc/passwd 来显示系统密码文件的内容。为方便起见,您应该用 less 查看大文件,如在 less /etc/passwd 中那样(您可以通过输入 man less 学习更多关于 less 的知识)。

尽管 cat 主要用于合并文件,您还可以将它用于输入的简单自动处理。例如,您可以使用一个单独的空白行来除去多行空白行(使用 -s 选项),这是一个在您将源代码公诸于世前进行清除工作的好办法。遗憾的是,cat 并没有用于一次清除所有空白行的选项。但这并不是什么大问题,因为您可以使用方便的 sed 命令将这些空白行除去:
清单 1. 使用 sed 与 cat 除去空白行


$ cat -s /etc/X11/XF86Config | sed '/^[[:space:]]*$/d'

...

# Multiple FontPath entries are allowed (they are concatenated together)

# By default, Red Hat 6.0 and later now use a font server independent of

# the X server to render fonts.

    FontPath   "/usr/X11R6/lib/X11/fonts/TrueType"

    FontPath   "unix/:7100"

EndSection

...

对于读取配置文件和 HTML 页面的源文件,特别是那些由脚本生成的插入了不必要新行的源文件,以及那些包含大型条件结构(其各个项之间已经用空行分开)的源文件来说,空白行紧缩是一个方便的技巧。

cat 的另外一个重要的功能是它可以对行进行编号。这种功能对于程序文档的编制以及法律和科学文档的编制很方便。打印在左边的行号使得参考文档的某一部分变得容易。这在编程、科学研究、业务报告或甚至是立法工作中都是非常重要的。对行进行编号功能有两个选项:-b 选项(只能对非空白行进行编号)和 -n 选项(可以对所有行进行编号):
清单 2. 对行进行编号


$ cat -b /etc/X11/XF86Config

...


    14  # Multiple FontPath entries are allowed (they are concatenated together)

    15  # By default, Red Hat 6.0 and later now use a font server independent of

    16  # the X server to render fonts.

    17      FontPath   "/usr/X11R6/lib/X11/fonts/TrueType"

    18      FontPath   "unix/:7100"

    19  EndSection
...

$ cat -n /etc/X11/XF86Config

...


    20  # Multiple FontPath entries are allowed (they are concatenated together)

    21  # By default, Red Hat 6.0 and later now use a font server independent of

    22  # the X server to render fonts.

    23  

    24      FontPath   "/usr/X11R6/lib/X11/fonts/TrueType"

    25      FontPath   "unix/:7100"

    26  

    27  EndSection

...

cat 还可以在您查看包含如制表符这样的非打印字符的文件时起帮助作用。您可以用以下选项来显示制表符:

    * -T 将制表符显示为 ^I
    * -v 显示非打印字符,除了换行符和制表符,它们使用各自效果相当的“控制序列”。例如,当您处理一个在 Windows 系统中生成的文件时,这个文件将使用 Control-M(^M)来标记行的结束。对于代码大于 127 的字符,它们的前面将会被加上 M-(表示“meta”),这与其它系统中在字符前面加上 Alt- 相当。
    * -E 在每一行的结束处添加美元符($)。

清单 3. 显示非打印字符


$ cat -t /etc/X11/XF86Config
...

# Multiple FontPath entries are allowed (they are concatenated together)

# By default, Red Hat 6.0 and later now use a font server independent of

# the X server to render fonts.


^IFontPath^I"/usr/X11R6/lib/X11/fonts/TrueType"

^IFontPath^I"unix/:7100"

EndSection
...


$ cat -E /etc/X11/XF86Config

...

# Multiple FontPath entries are allowed (they are concatenated together)$

# By default, Red Hat 6.0 and later now use a font server independent of$

# the X server to render fonts.$

$

    FontPath   "/usr/X11R6/lib/X11/fonts/TrueType"$

    FontPath   "unix/:7100"$

$

EndSection$

...

$ cat -v /etc/X11/XF86Config
...

^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@M-|M-8^X^@^@^@

P^@^O"M-X^O M-@^M^@^@^@M-^@^O"M-@M-k^@M-8*^@

@M-^H$M-@M-9|A(M-@)M-yM-|M-sM-*M-hW^A^@^@j^@

M-|M-sM-%1M-@M-9^@^B^@^@M-sM-+fM-^A= ^@ ^@

F^@^@   ^@M-9^@^H^@^@M-sM-$M-G^E(l!M-@M-^?

^IM-A5^@^@^D^@PM-^]M-^\X1M-H%^@^@^D^@tyM-G
...