4.4 用cut按列切分文件
我们也许不需要按行,而是需要按列切分文件。假设我们有一个文本文件,其中按行包含了学生的报表信息,例如No(学号)、Name(姓名)、Mark(成绩)和Percentage(百分比)。我们需要将学生的姓名提取到另一个文件,或者是需要表中的第n列或其中两列甚至更多列。这则攻略将为你演示如何完成这项任务。
4.4.1 预备知识
cut
是一个帮我们将文本按列进行切分的小工具。它也可以指定分隔每列的定界符。在cut
的术语中,每列都是一个字段。
4.4.2 实战演练
为了提取第一个字段或列,可以使用下面的语法:
- cut -f FIELD_LIST filename
FIELD_LIST
是需要显示的列。它由列号组成,彼此之间用逗号分隔。例如:
- $ cut -f 2,3 filename
这条命令将显示第2列和第3列。
cut
也能够从stdin
中读取输入文本。
制表符是字段或列的默认定界符。没有定界符的行也会照原样被打印出来。要避免打印出这种不包含定界符的行,则可以使用cut
的 -s
选项。一个cut
命令的例子如下:
- $ cat student_data.txt
- No Name Mark Percent
- 1 Sarath 45 90
- 2 Alex 49 98
- 3 Anu 45 90
- $ cut -f1 student_data.txt
- No
- 1
- 2
- 3
提取多个字段:
- $ cut -f2,4 student_data.txt
- Name Percent
- Sarath 90
- Alex 98
- Anu 90
要打印多列,需要提供一个由逗号分隔的列号列表作为-f
选项的参数。
我们也可以用 --complement
选项对提取的字段进行补集运算。假设有多个字段,你希望打印出除第3列之外所有的列,则可以使用:
- $ cut -f3 --complement student_data.txt
- No Name Percent
- 1 Sarath 90
- 2 Alex 98
- 3 Anu 90
要指定字段的定界符,使用 -d
选项:
- $ cat delimited_data.txt
- No;Name;Mark;Percent
- 1;Sarath;45;90
- 2;Alex;49;98
- 3;Anu;45;90
- $ cut -f2 -d";" delimited_data.txt
- Name
- Sarath
- Alex
- Anu
4.4.3 补充内容
cut
命令有一些选项可以将一串字符作为列来显示。让我们来看看这些选项。
指定字段的字符或字节范围
假设我们不依赖定界符,但需要通过将字段定义为一个字符范围(行首记为0)来进行字段提取,这种需求也可以用cut
来实现。
表4-4中列出了字符字段范围的记法。
表 4-4
记 法 | 范 围 |
---|---|
N- | 从第N个字节,字符或字段到行尾 |
N-M | 从第N个字节,字符或字段到第M个(包括第M个在内)字节、字符或字段 |
-M | 第1个字节,字符或字段到第M个(包括第M个在内)字节、字符或字段 |
用上面介绍的记法,再结合下列选项将某个范围的字节或字符指定为字段:
-b
表示字节;-c
表示字符;-f
表示定义字段。
例如:
- $ cat range_fields.txt
- abcdefghijklmnopqrstuvwxyz
- abcdefghijklmnopqrstuvwxyz
- abcdefghijklmnopqrstuvwxyz
- abcdefghijklmnopqrstuvwxy
你可以打印第1个到第5个字符:
- $ cut -c1-5 range_fields.txt
- abcde
- abcde
- abcde
- abcde
打印前2个字符:
- $ cut range_fields.txt -c-2
- ab
- ab
- ab
- ab
若要用字节作为计数单位,可以将 -c
替换成 -b
。
在使用 -c
、-f
和 -b
时,我们可以指定输出定界符:
--output-delimiter "delimiter string"
当用-b
或-c
提取多个字段时,必须使用 --output-delimiter
,否则,你就没法区分不同的字段了。例如:
- $ cut range_fields.txt -c1-3,6-9 --output-delimiter ","
- abc,fghi
- abc,fghi
- abc,fghi
- abc,fghi