上古神器 awk 笔记

2022-11-15 21:38:05 浏览数 (1)

awk基本格式

代码语言:javascript复制
awk '{ awk program }' file

file 为 awk 要读取的文件,可以是一个或多个文件。如果不指定文件,则从标准输入中读取

代码语言:javascript复制
awk '{ awk program }' a.txt b.txt c.txt

单引号内的是awk的程序,一般使用单引号而非双引号。 awk是按行处理文件,内部有一个隐藏的循环,即默认下逐行读取文件并运行程序

使用单引号原因:双引号中的$会被 shell 解析成 shell 变量引用,于是会进行 shell 变量替换。为了表示awk程序使用的变量,所以尽可能使用单引号

awk 程序中的 {} 表示代码块

代码语言:javascript复制
awk '{print $0}' a.txt
awk '{print $0}{print $0; print $0}' a.txt

BEGINEND 语句块

代码语言:javascript复制
awk 'BEGIN{print "俺要开始读文件啦"}{print $0}END{print "俺处理完文件啦"}' a.txt
  • BEGIN 代码块: 在读取文件前行执行一次,不参与awk的隐藏循环
  • END 代码块: 在读取文件完成后执行一次,不参与awk的隐藏循环
  • main 代码块:不以BEGINEND开头的代码块都称之为 main 代码块, main 代码块会参与 awk 的隐藏循环

awkpattern 和 action

代码语言:javascript复制
awk '
BEGIN {
    n=3
}
/^[0-9]/ {
    print $1
}
END {
    print "end"
}
' a.txt

awk语法格式为pattern { action }模式, 称之为awkrule

  • pattern 用于筛选符合的文本行
  • action 表示筛选通过后执行的操作
  • pattern 和 action 都可省略
    • 省略 pattern 则不筛选数据,表示对每一行数据都执行 action
    • 省略 {action} 表示对每一行都执行 {print}
    • 省略 action 表示对筛选的行不做任何操作,该语法实际使用中并无意义

可以将 BEGIN 与 END 代码块看成一种特殊的 pattern{action} 代码块

代码语言:javascript复制
# bool pattern
/regular expression/   # 正则匹配,e.g., /a.*ef/{action}
relational expression  # 大小关系匹配,e.g., 3>2{action}
pattern && pattern     # 逻辑与
pattern || pattern     # 逻辑或
!pattern               # 逻辑反
pattern ? pattern : pattern  # 三目运算符

# 范围 pattern
pattern1, pattern2     # 范围匹配,匹配从 pattern1 到 pattern2 之间的内容

awk 读取文件

记录分隔符

awk读取文件时, 每读取一条记录(Record)(默认下按行读取,一行就是一条记录). 每读取一条记录,将其保存到$0中,然后执行一次 main 代码段。

可通过修改预定义变量RS来改变每次读取的记录模式,RS变量表示输入记录分隔符(Record Separator),默认值为n

RS一般设置在 BEGIN 代码块中,因为需要在读取文件前确定好分隔符

注:RS变量作为输入记录分割符,所读取的每条记录不包含RS变量值

  • RS 为单个字符, 则直接用该字符来分割记录
  • RS 为多个字符,则将其作为正则表达式,只要匹配上正则表达式都用来分割记录
    • 设置预定义变量IGNORECASE为非零值,正则匹配时忽略大小写

特殊RS值解决特定需求:

代码语言:javascript复制
RS=""    # 按段落读取
RS="^$"  # 一次性读取所有数据, 该正则只能匹配空文件
RS="n " # 按行读取,但忽略所有空行

awk每读取一条记录时,会设置预定义变量RT表示记录分割符(Record Termination)。 当RS为单个字符时,RT的值和RS值相同。 当RS为正则表达式时,RT`为正则匹配的记录分隔符

行号

awk读取每条记录后,将其赋值给$0和设置RT外,还会设置NRFNR这两个预定义变量

  • NR: 所有文件的行号计数器
  • FNR: 各个文件的行号计数器,针对于多个文件输入的情况

字段分割

awk读取每条记录后,将其赋值给0,同时还会对该条记录按照预定义变量FS划分字段,将划分后的各个字段依次存入 1,2, 3 …,同时将划分好的字段数量赋值给预定义变量NF

代码语言:javascript复制
awk '{print $NF}' a.txt   # 输出 a.txt 的最后一列

未完待续 ~~

本文作者: Ifan Tsai  (菜菜)

本文链接: https://cloud.tencent.com/developer/article/2164605

版权声明: 本文采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!

0 人点赞