1. awk命令简介
awk是专门为文本处理设计的编.程语言,也是一个应用程序,几乎所有Linux发行版本都自带这个程序。我们通常用它进行数据扫描、过滤、统计汇总工作。
- awk是一种强大的编辑工具,比较倾向于一行当中分成数个字段来处理,因为awk相当适合小型的文本数据。
- awk 比较倾向于将一行分成多个字段然后再进行处理,且默认情况下字段的分隔符为空格或 tab 键。awk 执行结果可以通过 print 的功能将字段数据打印显示。
awk工作原理
- 逐行读取文本,默认以空格或tab键为分隔符进行分隔,将分隔所得的各个字段保存到内建变量中,并按模式或者条件执行编辑命令。
- 在使用awk命令的过程中,可以使用逻辑操作符“&&”表示“与”、“||”表示“或”、“!”表示“非”;还可以进行简单的数学运算,如+、-、*、/、%、^分别表示加、减、乘、除、取余和乘方。
2. awk命令格式
它与grep、sed命令一样都是以行为单位读取文本的,默认以空格或Tab键为分隔符,将分割所得的各个字段保存到内建变量中供后续使用。
命令格式如下:
awk "[选项1] {操作1;操作2} [选项2] {操作3;操作4} ..." 文件名awk -f 脚本文件 文件名
awk语法由一系列选项和操作组成,在花括号内可以有多个操作,在多个操作之间是有分号分隔,在多个选项和操作之间可以有若干空格,也可以没有
选项说明:
-F fs or --field-separator fs:相当于内建变量“FS”,指定分割符为fs,默认为空格或Tab制表符;
-f scripfile or --file scriptfile:从文件中读取awk指令,用来代替命令行中输入的命令;
-v var=value or --asign var=value:设置一个变量并且附上初值。
3. awk常见的内置变量和运算符
常见的内置变量如下:
内置变量 | 说明 |
---|---|
$0 | 当前记录(作为单个变量),即当前处理的行的字段个数 |
FS | 列分割符指定每行文本的字段分隔符,默认为空格或制表位。也可用选项"-F"表示 |
NF | 当前处理行的字段个数,即列数,从1开始 |
NR | 当前记录中的行数,从1开始 |
$n | 当前处理行的第n个字段(第n列) |
RS | 行分隔符。awk从文件上读取资料时,将根据RS的定义把资料切割成许多条记录,而awk一次仅读入一条记录,以进行处理。预设值是’\n’ |
FILENAME | 被处理的文件名 |
FNR | 当awk处理多个文件时,分别对每个文件的行数进行计数 |
ORS | 更改行换行符 |
OFS | 更改列分割符 |
ARGV | 表示是一个数组,这个数组中保存的是命令行所给定的参数 |
ARGC | 表示参数的数量,也可以理解为ARGV数组的长度 |
运算符
运算符 | 描述 |
---|---|
= += -= *= /= %= ^= **= | 赋值 |
?: | C语言中的三目运算符 |
< <= > >= != == | 关系运算 |
+ - * / % | 算术运算 |
^ ** | 求幂 |
++ -- | 自增和自减 |
||和&& | 逻辑或/与 |
$ | 字段引用 |
in | 数组成员 |
4. awk常见用法汇总
4.1 基础用法
示例,编写一个test.txt文本
root@ubuntu:/home/zgx/Desktop# cat test.txt # 查看文本内容this is a test filehello,world!bye byehayear, month, day, hour, minute, secondroot@ubuntu:/home/zgx/Desktop# awk "{print NF}" test.txt # 使用NF显示每行的列数5126root@ubuntu:/home/zgx/Desktop# awk "{print $NR}" test.txt # 打印显示当前每行记录this is a test filehello,world!bye byehayear, month, day, hour, minute, second
4.1.1 打印指定列的内容
使用$1,$4打印第1列、第4列的内容
root@ubuntu:/home/zgx/Desktop# awk '{print $1,$4}' test.txt # 普通输出this testhello,world!bye year, hour,root@ubuntu:/home/zgx/Desktop# awk '{printf "%-10s %-10s\n",$1,$4}' test.txt # 格式化输出this test !bye year, hour,
注意:print与printf的区别:
1)printf用于格式化输出
2)printf默认是不带换行符号的,所以要换行需要带上\n
4.1.2 打印指定分隔符的内容
指定英文逗号“,”为分隔符
root@ubuntu:/home/zgx/Desktop# awk -F',' '{print $1,$4}' test.txtthis is a test filehello bye byehayear hour
4.1.3 打印多个分隔符的内容
指定多个分割符输出(首先使用空格,然后在使用其他分割符)
root@ubuntu:/home/zgx/Desktop# awk -F '[, ]' '{print NF}' test.txt # 查看分隔后的每行列数52211root@ubuntu:/home/zgx/Desktop# awk -F '[, ]' '{print $1,$2,$3}' test.txtthis is ahello world!bye byehayear [空格] month
4.2 进阶用法
4.2.1 打印指定行的内容
打印第i到第j行的内容(两种方法)
root@ubuntu:/home/zgx/Desktop# awk 'NR==2,NR==4{print}' test.txt # 打印第2到第4的内容root@ubuntu:/home/zgx/Desktop# awk 'NR==2,NR==4' test.txt # {print}可要可不要hello,world!bye byehayear, month, day, hour, minute, secondroot@ubuntu:/home/zgx/Desktop# awk '(NR>=2)&&(NR<=4){print}' test.txt # 打印第2到第4的内容root@ubuntu:/home/zgx/Desktop# awk '(NR>=2)&&(NR<=4)' test.txt # {print}可要可不要hello,world!bye byehayear, month, day, hour, minute, second
打印第i、第j行的内容
root@ubuntu:/home/zgx/Desktop# awk 'NR==2 || NR==4' test.txt # 打印第2、第4行的内容hello,world!year, month, day, hour, minute, second
4.2.2 支持正则表达式
显示text2.txt文本内容如下
root@ubuntu:/home/zgx/Desktop# cat test2.txtthis is a test filehello,world!bye byehayear, month, day, hour, minute, secondhahahahello everybodyaaaaaaaaa
输出以h、he开头的行
root@ubuntu:/home/zgx/Desktop# awk '/^h/{print}' test2.txt # 打印以h开头的行hello,world!hahahahello everybodyroot@ubuntu:/home/zgx/Desktop# awk '/^he/' test2.txt # 打印以he开头的行hello,world!hello everybody
输出以d!为结尾的行
root@ubuntu:/home/zgx/Desktop# awk '/d!$/' test2.txthello,world!
输出第2列包含字符b的行
root@ubuntu:/home/zgx/Desktop# awk '$2 ~ /b/' test2.txtbye byehahello everybodyroot@ubuntu:/home/zgx/Desktop# awk '$2 !~ /b/' test2.txt # 输出第2列不包含字符b的行this is a test filehello,world!year, month, day, hour, minute, secondhahahaaaaaaaaaa
4.2.3 根据运算符过滤指定的行
显示test3.txt文本的内容如下:
root@ubuntu:/home/zgx/Desktop# cat test3.txt101 this is a test file102 hello world!203 bye byeha204 year, month, day, hour, minute, second205 fawffno number206,aaaaaaaa
输出第i列数值在指定范围的行
root@ubuntu:/home/zgx/Desktop# awk '$1>200' test3.txt # 输出第1列数值大于200的行203 bye byeha204 year, month, day, hour, minute, second205 fawffno number206,aaaaaaaaroot@ubuntu:/home/zgx/Desktop# awk '$1>300' test3.txt # 输出第1列数值大于300的行no number
输出第1列小于100且第2列字符串为“hello”的行
root@ubuntu:/home/zgx/Desktop# awk '$1<200 && $2=="hello"' test3.txt102 hello world!
4.2.4 输出与指定内容相反的行
输出以非h开头的行
root@ubuntu:/home/zgx/Desktop# awk '!/^h/' test2.txt # 打印以非h开头的行this is a test filebye byehayear, month, day, hour, minute, secondaaaaaaaaa
输出第1列数值非大于200的行
root@ubuntu:/home/zgx/Desktop# awk '!($1>200)' test3.txt101 this is a test file102 hello world!
4.2.5 设置变量
root@ubuntu:/home/zgx/Desktop# awk -F'[, ]' -va=1 -vb=sss '{print $1,$1+a,$1a,$1b}' test3.txt101 102 1011 101sss102 103 1021 102sss203 204 2031 203sss204 205 2041 204sss205 206 2051 205sssno 1 no1 nosss206 207 2061 206sss
4.3 字符串函数
函数 | 说明 |
---|---|
length() | 返回字符串的长度 |
index() | 返回下标 |
tolower() | 转换成小写并返回字符串 |
toupper() | 转换成大写并返回字符串 |
substr() | 返回字符串中的子串 |
match() | 返回下标,但它不搜索子串 |
sub() | 替换匹配的第一个字符串序列,并返回整个字符串 |
gsub() | 替换匹配的所有字符串序列,并返回整个字符串 |
split() | 分割字符串并将各部分放到使用整数下标的数组中 |
打印各行字符串的长度
root@ubuntu:/home/zgx/Desktop# cat test2.txtthis is a test filehello,world!bye byehayear, month, day, hour, minute, secondhahahahello everybodyaaaaaaaaaroot@ubuntu:/home/zgx/Desktop# awk '{print length()}' test2.txt19129386159
打印字符串长度超过15的行
root@ubuntu:/home/zgx/Desktop# awk 'length>15' test2.txtthis is a test fileyear, month, day, hour, minute, second
字符串大小写转换
root@ubuntu:/home/zgx/Desktop# awk '{print $1, tolower($2), toupper($3)}' test2.txtthis is Ahello,world! bye byeha year, month, DAY,hahaha hello everybody aaaaaaaaa
打印每行的最后两个字符
root@ubuntu:/home/zgx/Desktop# awk '{print substr($0,length($0)-1)}' test2.txtled!handhadyaa
4.4 BEGIN/END关键字
默认情况下awk是从输入中读取一行字符串,然后对该行执行相应的命令,而有时候想在执行这些命令之前先进行一些其他的脚本命令,则可以使用BEGIN关键字,而END关键字的处理时机则刚好相反。
代码示例:
root@ubuntu:/home/zgx/Desktop# awk 'BEGIN{print "---file start---"} {print $1,$4} END{print "---file end---"}' test2.txt---file start---this testhello,world! bye year, hour,hahaha hello aaaaaaaaa ---file end---
来源地址:https://blog.csdn.net/m0_46201294/article/details/128314651