目录

Awk学习

题记

awk是unix下很实用的文本编辑语言。可以快速处理很多操作。参考资料是b站up主正月点灯笼的awk入门教程。这篇博客用来记录一下awk里面非常基础的操作。

待处理的文本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz josef 100 Korona
silver 10 1981 USA ingot
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
silver 1 1986 USA Liberty dollar
gold 0.25 1986 USA Liberty 5-dollar piece
silver 1 1986 USA Liberty 50-cent piece
silver 1 1987 USA Constitution dollar
gold 0.25 1987 USA Constitution 5-dollar piece
gold 1 1988 Canada Maple leaf

命名为coins.txt, 每一列从左到右分别表示材料、重量、生产时间、生产地、产品名称。

打印内容

  • awk '{print NR "\t" $0 "\t" $5}' coins.txt'

知识点

  1. 行是record,列是field。打印行号用NR
  2. $1表示第一列
  3. $0表示打印全部内容
  4. 注意原本设想的产品名称 列被拆成了多列,比如American Eagle被拆成了2列。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
1	gold 1 1986 USA American Eagle	American
2	gold 1 1908 Austria-Hungary Franz josef 100 Korona	Franz
3	silver 10 1981 USA ingot	ingot
4	gold 1 1984 Switzerland ingot	ingot
5	gold 1 1979 RSA Krugerrand	Krugerrand
6	gold 0.5 1981 RSA Krugerrand	Krugerrand
7	gold 0.1 1986 PRC Panda	Panda
8	silver 1 1986 USA Liberty dollar	Liberty
9	gold 0.25 1986 USA Liberty 5-dollar piece	Liberty
10	silver 1 1986 USA Liberty 50-cent piece	Liberty
11	silver 1 1987 USA Constitution dollar	Constitution
12	gold 0.25 1987 USA Constitution 5-dollar piece	Constitution
13	gold 1 1988 Canada Maple leaf	Maple
  • awk '{print NR NR, NR}' coins.txt

知识点:用,逗号来分开,只用空格会被直接忽略掉。

NR NR的打印结果中间没有空格,而NR, NR打印结果是有空格的(注意命令中逗号后面有一个空格)。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
11 1
22 2
33 3
44 4
55 5
66 6
77 7
88 8
99 9
1010 10
1111 11
1212 12
1313 13

搜索

  • awk '$3==1986{print $0}' coins.txt

打印满足第三列是1986的所有行。

1
2
3
4
5
gold 1 1986 USA American Eagle
gold 0.1 1986 PRC Panda
silver 1 1986 USA Liberty dollar
gold 0.25 1986 USA Liberty 5-dollar piece
silver 1 1986 USA Liberty 50-cent piece
  • awk '$3==1986&&$1=="gold"{print $0}' coins.txt

知识点:对字符串的匹配要加上双引号,否则会被当做变量名

1
2
3
gold 1 1986 USA American Eagle
gold 0.1 1986 PRC Panda
gold 0.25 1986 USA Liberty 5-dollar piece

分割符

为了方便演示,使用Hello,world作为输入。

知识点

  1. awk分割符分为输入分割符和输出分割符
  2. BEGIN 模式:是指 awk 将在读取任何输入行之前立即执行BEGIN 中指定的动作
  3. 和C语言一样,分号;用来分开多个语句
  • echo Hello,world | awk '{print $1, NF}'

    输出:Hello,world 1

  • echo Hello,world | awk 'BEGIN{FS=","} {print $1, $2, NF}'

    输出:Hello world 2

  • echo Hello,world | awk 'BEGIN{FS=","; OFS=","} {print $1, $2, NF}'

    输出:Hello,world,2

变量

  • awk '{$3="xxx"; print FILENAME $0}' coins.txt

知识点

  1. FILENAME可以输出文件名,比如coins.txt.
  2. $3="xxx"把第三列替换了
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
coins.txtgold 1 xxx USA American Eagle
coins.txtgold 1 xxx Austria-Hungary Franz josef 100 Korona
coins.txtsilver 10 xxx USA ingot
coins.txtgold 1 xxx Switzerland ingot
coins.txtgold 1 xxx RSA Krugerrand
coins.txtgold 0.5 xxx RSA Krugerrand
coins.txtgold 0.1 xxx PRC Panda
coins.txtsilver 1 xxx USA Liberty dollar
coins.txtgold 0.25 xxx USA Liberty 5-dollar piece
coins.txtsilver 1 xxx USA Liberty 50-cent piece
coins.txtsilver 1 xxx USA Constitution dollar
coins.txtgold 0.25 xxx USA Constitution 5-dollar piece
coins.txtgold 1 xxx Canada Maple leaf
  • awk '{print $NF "\t" $(NF-1)}' coins.txt

知识点$NF可以用来打印倒数第某列

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Eagle	American
Korona	100
ingot	USA
ingot	Switzerland
Krugerrand	RSA
Krugerrand	RSA
Panda	PRC
dollar	Liberty
piece	5-dollar
piece	50-cent
dollar	Constitution
piece	5-dollar
leaf	Maple

正则表达式

  • awk '/^g/{print $0}' coins.txt

匹配开头是g的行。

1
2
3
4
5
6
7
8
9
gold 1 1986 USA American Eagle
gold 1 1908 Austria-Hungary Franz josef 100 Korona
gold 1 1984 Switzerland ingot
gold 1 1979 RSA Krugerrand
gold 0.5 1981 RSA Krugerrand
gold 0.1 1986 PRC Panda
gold 0.25 1986 USA Liberty 5-dollar piece
gold 0.25 1987 USA Constitution 5-dollar piece
gold 1 1988 Canada Maple leaf

正则表达式语法:

  • .匹配任何单字符,要匹配 . ,需使用 \.

    /a.c/ 能够匹配abc, axc等

  • ^$分别表示开始和结尾

  • []表示匹配方括号中的一个字符

    /a[xy]b/能够匹配axb, ayb.

    /a[a-zA-Z]b/能够匹配axb, aXb等.

  • ^在方括号中表示否定

    /a[^a-z]c/能够匹配aAc,但不能匹配aac.

  • *表示可以匹配0次或多次

  • +表示匹配1次或多次

  • ?表示前面的字符可以有也可以没有

    /a?b/可以匹配ab,b。

  • {}用于匹配多个重复字符

    /a{3}c/可匹配aaac。

    /a{1,3}c/可匹配ac,aac,aaac。

    /a{2,}c/可匹配aac,aaaaac等。

  • ()标记一个子表达式的开始和结束位置

    /(ab)+c/可匹配abc, ababababc.