Linux文本处理三剑客之awk

工欲善其事,必先利其器。

掌握了Linux文本三剑客,可谓是事半功倍。

对于刚接触Linux的同学来说,Linux的各种命令真的时让人望而生畏。工作中看到大神们一通操作猛如虎,各种命令以及参数眼花缭乱。

当我们用过一些命令,但又不熟悉得情况下,这个时候就得从全局入手,看看Linux有哪几类命令,先提纲挈领,至少我们能知道完成什么样得功能我需要用什么命令,至于细节参数,查手册多用几次就熟悉了。而不是每次都束手无策,盲目查找。

今天我们就来看一下Linux对于文本处理的三大利器之一awk。基本上可以满足对文本处理的所有任务。

awk

简介

AWK是Linux强大的文本处理工具,其名称由来取自于三位创始人姓氏的首字母。
AWK擅长行处理,其工作原理:

  1. awk会接收一行作为输入,并将这一行赋给awk的内部变量$0,每一行也可称为一个记录,行的边界是以换行符作为结束;
  2. 读入的行以分隔符(默认为空格,可以自己指定)分解成若干字段(或域),每个字段存储在已编号的变量中,编号从$1开始,最多达100个字段;
  3. 一行处理完,将从文件中获取另一行,然后覆盖给$0,继续(2)的步骤,直至所有行处理完毕。

命令格式

awk [options] 'pattern {action}' file1 file2, ...
awk [options] 'script' file1 file2, ...

pattern: 模式或条件

action: 对数据处理,常用print

常用内建变量

FS: 输入列分隔符。指定每行文本的字段分割符,默认为空格或者治标位。与“-F”作用相同

OFS: 输出列分隔符

NF: 当前处理的行的字段个数;

NR: 当前处理的行的行号;

$0: 当前处理的行的整行内容;

$n: 当前处理行的第n个字段;

FILENAME: 被处理的文件名

常用参数

-F fs or --field-separator fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
-v var=value or --asign var=value
赋值一个用户定义变量。
-f scripfile or --file scriptfile
从脚本文件中读取awk命令。

基本用法

创建测试文件test.txt;

(base) rhett@LAPTOP-MV0SUCM6:~$ cat test.txt
Today is a good day, a sunny day, a wonderful day, a important day.
I am a boy, a good boy, a lovely boy.
I like reading, sports, and coding.
Enjoy coding.

案例1

按行输出:输出文件的1~3行
NR是内建变量,代表行号

(base) rhett@LAPTOP-MV0SUCM6:~$ awk '(NR>=1)&&(NR<=3)' test.txt
Today is a good day, a sunny day, a wonderful day, a important day.
I am a boy, a good boy, a lovely boy.
I like reading, sports, and coding.

案例2

按字段输出:输出每行中的第1、3个字段(默认空格分割符)

(base) rhett@LAPTOP-MV0SUCM6:~$ awk '{print $1,$3}' test.txt
Today a
I a
I reading,
Enjoy

这里的输出分隔符默认和输入一样,为空格。

我们也可以指定输出分隔符;
-v给变量赋值,这里给内建变量输出分隔符OFS赋值为“#”

(base) rhett@LAPTOP-MV0SUCM6:~$ awk -v OFS='#' '{print $1,$3}' test.txt
Today#a
I#a
I#reading,
Enjoy#

案例3

按照指定分隔符分割字段。

下面按照逗号而不是空格重新分割输出。

(base) rhett@LAPTOP-MV0SUCM6:~$ awk -v OFS='#' -F , '{print $1,$2}' test.txt
Today is a good day# a sunny day
I am a boy# a good boy
I like reading# sports
Enjoy coding.#

案例4

输出分段输大于3的行。

注意是以逗号为分隔符,只有第一行为4个字段,其他都少于等于3个字段。

(base) rhett@LAPTOP-MV0SUCM6:~$ awk -F ',' 'NF>3 {print $1,$2}' test.txt
Today is a good day  a sunny day

进阶用法

处理规则

  1. BEGIN{} : BEGIN是在awk处理文本之前运行
  2. // : 使用的匹配规则
  3. {} :循环(每次只处理一行数据)
  4. END{} :当所有的处理全部执行完毕之后,执行END中的相关操作

正则表达式

参考 https://www.runoob.com/regexp/regexp-syntax.html

案例5

匹配含有“good”的行。

(base) rhett@LAPTOP-MV0SUCM6:~$ awk '/good/' test.txt
Today is a good day, a sunny day, a wonderful day, a important day.
I am a boy, a good boy, a lovely boy.

案例6

输出文件参数

(base) rhett@LAPTOP-MV0SUCM6:~$ awk 'BEGIN{printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n","FILENAME","ARGC","FNR","FS","NF","NR","OFS","ORS","RS";printf "---------------------------------------------\n"} {printf "%4s %4s %4s %4s %4s %4s %4s %4s %4s\n",FILENAME,ARGC,FNR,FS,NF,NR,OFS,ORS,RS}' test.txt
FILENAME ARGC  FNR   FS   NF   NR  OFS  ORS   RS
---------------------------------------------
test.txt    2    1        14    1


test.txt    2    2        10    2


test.txt    2    3         6    3


test.txt    2    4         2    4


posted @ 2023-08-06 17:31  百里骑  阅读(45)  评论(0)    收藏  举报