Linux 命令:awk

1. 写在前面

本文主要介绍 Linux “awk” 命令:“awk” 是另一个强大的文本处理工具,用于处理和操作结构化数据,如日志文件和命令输出。它可以根据需要为我们打印特定的列值。

公众号: 滑翔的纸飞机

2. awk 命令

我们能用 awk 做什么?awk 处理文本数据,不管是从文件来的或者数据流中来的。输入数据被区分为记录和文本域。 awk 一次处理一条记录,一直到输入结束。

  • awk 操作:

(1) 逐行扫描文件;
(2) 将每个输入行分割成字段;
(3) 将输入行/字段与匹配规则进行比较;
(4) 对匹配的行执行操作;

  • 适用于:

(1) 转换数据文件;
(2) 生成格式化报告;

  • 编程结构:

(1) 输出行格式化;
(2) 算术和字符串运算;
(3) 条件和循环;

awk 命令的基本语法是:

awk [ -F fs ] [ -v var=value ] [ 'prog' | -f progfile ] [ file ...  ]

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

备注: 示例文本文件:text.txt、text2.txt

cat > ./text.txt
---------------------------------------------------
Dwight Frances manager account 45000
Lindsay Max clerk account 25000
Jo Richardson manager sales 50000
Rosalind Watt manager account 47000
Gale Evelina peon sales 15000
Baron Eveline clerk sales 23000
Will Pater peon sales 13000
Christopher Noah director purchase 80000
cat > ./text2.txt
---------------------------------------------------
A    B    C

Tarun    A12    1
Man    B6    2
Praveen    M42    3

2.1 简单示例

(1)awk 的默认行为

默认情况下,awk 会打印指定文件中的每一行数据。

root@dev:~/linux# awk '{print}' text.txt 
---------------------------------------------------
Dwight Frances manager account 45000
Lindsay Max clerk account 25000
Jo Richardson manager sales 50000
Rosalind Watt manager account 47000
Gale Evelina peon sales 15000
Baron Eveline clerk sales 23000
Will Pater peon sales 13000
Christopher Noah director purchase 80000

在上述示例中,没有给出任何模式。因此操作适用于所有行。不带任何参数的 print 参数默认打印整行,因此它可以打印文件的所有行,不会出现失败。

(2)打印与给定模式匹配的行

root@dev:~/linux# awk '/manager/ {print}' text.txt 
---------------------------------------------------
Dwight Frances manager account 45000
Jo Richardson manager sales 50000
Rosalind Watt manager account 47000

在上例中,awk 命令会打印所有与 "manager "匹配的行。

**备注:**一个正则表达式匹配一系列字符串。awk 正则表达式样式使用//来包裹,可以是任何一种其他的正则表达式。这是一个例子,打印任何以两个或者更多数字开头的记录的第一个文本域:

root@dev:~/linux# awk '/^[A-B][a-z]/ { print $1,$2 }' text.txt
---------------------------------------------------------------
Baron Eveline

(3)将一行拆分为多个字段

对于每条记录(即行),awk 命令默认以空格字符分割记录,并将其存储在 $n 变量中。如果一行有 4 个字段,则分别存储在 $1、$2、$3 和 $4 中。另外,$0 代表整行。

root@dev:~/linux# awk '{print $1,$2,$5}' text.txt 
---------------------------------------------------
Dwight Frances 45000
Lindsay Max 25000
Jo Richardson 50000
Rosalind Watt 47000
Gale Evelina 15000
Baron Eveline 23000
Will Pater 13000
Christopher Noah 80000

在上例中,$1,$2$5 分别代表姓名和薪金字段。

(4)打印文本中每一行的第一个字段以及用"-"分隔的行号

root@dev:~/linux# awk '{print NR " - " $1,$2 }' text.txt 
-------------------------------------------------------------
1 - Dwight Frances
2 - Lindsay Max
3 - Jo Richardson
4 - Rosalind Watt
5 - Gale Evelina
6 - Baron Eveline
7 - Will Pater
8 - Christopher Noah

在上例中,$1,$2 代表姓名输出行号,“ - ”进行分割;

(5)如果存在,打印任何空行

root@dev:~/linux# awk 'NF == 0 {print NR}' text2.txt 
-------------------------------------------------------------
2

或者

root@dev:~/linux# awk 'NF <= 0 {print NR}' text2.txt 
-------------------------------------------------------------
2

(6) 查找文件中最长一行的长度

root@dev:~/linux# awk '{ if (length($0) > max) max = length($0) } END { print max }'  text.txt 
-------------------------------------------------------------------------------------
40

(7) 计算文件中的行数

root@dev:~/linux# awk 'END { print NR }'  text.txt 
------------------------------------------------------------------
8

(8) 打印超过 35 个字符的行

root@dev:~/linux# awk 'length($0) > 35'  text.txt 
------------------------------------------------------------------
Dwight Frances manager account 45000
Christopher Noah director purchase 80000

(9) 查找/检查任何特定列中的任何字符串

root@dev:~/linux# awk '$1 == "Dwight" { print $0 }' text.txt
------------------------------------------------------------------
Dwight Frances manager account 45000

或者:
root@dev:~/linux# awk '{ if($1 == "Dwight") print $0;}' text.txt 
------------------------------------------------------------------
Dwight Frances manager account 45000

(10)打印从 1 到 n 的第一个数字的平方,例如 6

root@dev:~/linux# awk 'BEGIN { for(i=1;i<=6;i++) print "square of", i, "is",i*i; }'
--------------------------------------------------------------------------------
square of 1 is 1
square of 2 is 4
square of 3 is 9
square of 4 is 16
square of 5 is 25
square of 6 is 36

(11) 计算文件大小

root@dev:~/linux# ls -l *.txt | awk '{sum+=$5} END {print sum}'
------------------------------------------------------------------
336

(12) 匹配包含 “manager” 直到 “account"记录

root@dev:~/linux# awk '/manager/,/account/ { print $0 }' text.txt 
------------------------------------------------------------------
Dwight Frances manager account 45000
Jo Richardson manager sales 50000
Rosalind Watt manager account 47000

2.2 awk 中的内置变量

awk 的内置变量包括字段变量–$1、$2、$3 等($0 表示整行)–它们将一行文本分割成单个单词或称为字段的片段。

变量描述
$n当前记录的第n个字段,字段间由FS分隔
$0完整的输入记录
ARGC命令行参数的数目
ARGIND命令行中当前文件的位置(从0开始算)
ARGV包含命令行参数的数组
CONVFMT数字转换格式(默认值为%.6g)ENVIRON环境变量关联数组
ERRNO最后一个系统错误的描述
FIELDWIDTHS字段宽度列表(用空格键分隔)
FILENAME当前文件名
FNR各文件分别计数的行号
FS字段分隔符(默认是任何空格)
IGNORECASE如果为真,则进行忽略大小写的匹配
NF一条记录的字段的数目
NR已经读出的记录数,就是行号,从1开始
OFMT数字的输出格式(默认值是%.6g)
OFS输出字段分隔符,默认值与输入字段分隔符一致
ORS输出记录分隔符(默认值是一个换行符)
RLENGTH由match函数所匹配的字符串的长度
RS记录分隔符(默认是一个换行符)
RSTART由match函数所匹配的字符串的第一个位置
SUBSEP数组下标分隔符(默认值是/034)

2.2.1 示例

(1)使用 NR 内置变量(显示行号)

root@dev:~/linux# awk '{print NR,$0}' text.txt 
---------------------------------------------------
1 Dwight Frances manager account 45000
2 Lindsay Max clerk account 25000
3 Jo Richardson manager sales 50000
4 Rosalind Watt manager account 47000
5 Gale Evelina peon sales 15000
6 Baron Eveline clerk sales 23000
7 Will Pater peon sales 13000
8 Christopher Noah director purchase 80000

在上例中,带有 NR 的 awk 命令会打印所有行以及行号。

(2)使用 NF 内置变量(显示最后字段)

root@dev:~/linux# awk '{print $1,$2,$NF}' text.txt 
Dwight Frances 45000
Lindsay Max 25000
Jo Richardson 50000
Rosalind Watt 47000
Gale Evelina 15000
Baron Eveline 23000
Will Pater 13000
Christopher Noah 80000

在上例中,$1,$2 代表姓名,$NF 代表薪金。我们可以使用 $NF 获取薪金,其中 $NF 代表最后一个字段。

(3) NR 内置变量的另一种用法(显示行从 3 到 6行)

root@dev:~/linux# awk 'NR==3, NR==6 {print NR,$0}' text.txt 
3 Jo Richardson manager sales 50000
4 Rosalind Watt manager account 47000
5 Gale Evelina peon sales 15000
6 Baron Eveline clerk sales 23000

在上例中,显示3 ~ 6行记录,显示行号;

(4) 忽略大小写

root@dev:~/linux# awk 'BEGIN{IGNORECASE=1} /evelina/' text.txt 
-----------------------------------------------------------------------
Gale Evelina peon sales 15000


root@dev:~/linux# awk 'BEGIN{IGNORECASE=1} /Evelina/' text.txt 
-----------------------------------------------------------------------
Gale Evelina peon sales 15000

(5) 打印文件名及行数

root@dev:~/linux# awk 'END { print "File", FILENAME, "contains", NR, "lines." }' text.txt 
-----------------------------------------------------------------------------------
File text.txt contains 8 lines.

更多示例后续不断补充。

感谢您花时间阅读文章!
关注公众号不迷路!
  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值