【Linux】文本处理三剑客之awk命令语法,内置变量

目录

一、awk基本概念

二、awk 命令语法

三、awk 程序结构(BEGIN,Body,END)区域

四、awk 内置变量

FS         

RS

ORS

FILENAME

OFS

NF

$NF与NF的区别

​编辑

NR

FNR

五、过滤

六、awk输出格式

%s字符串

七、awk编程语句

八、awk函数

九、printf 按照某一格式化输出文件


一、awk基本概念

        awk 是一个按需求格式化文本再进行输出的工具。

        和 sed 命令类似,awk 命令也是逐行扫描文件(从第 1 行到最后一行),寻找含有目标文本的行,如果匹配成功,则会在该行上执行用户想要的操作;反之,则不对行做任何处理。

        awk -f 脚本文件 数据文件  执行awk脚本文件

awk 的应用场景:

看下 awk 能干些什么事情:

1. 能够将给定的文本内容,按照我们期望的格式输出显示,打印成报表。
2. 分析处理系统日志,快速地分析挖掘我们关心的数据,并生成统计信息;
3. 方便地用来统计数据,比如网站的访问量,访问的 IP 量等;
4. 通过各种工具的组合,快速地汇总分析系统的运行信息,让你对系统的运行了如指掌;
5. 强大的脚本语言表达能力,支持循环、条件、数组等语法,助你分析更加复杂的数据;
awk 不是万能的,它比较擅长处理格式化的文本,比如 日志、 csv 格式数据等;

二、awk 命令语法

awk 基础语法:


awk

k –Fs ‘/pattern/ {action}’ input-file

(或者)

awk –Fs ‘{action}’ input-file


  •  -F 为字段分界符,也就是分隔符。如果不指定,默认会使用空格作为分界符。请注意,你也可以把分界符 用双引号引住,-F”:”也是正确的。
  • /pattern/和{action}需要用单引号引起来。
  • /pattern/是可选的。如果不指定,awk 将处理输入文件中的所有记录。如果指定一个模式,awk 则只处理匹配指定的模式的记录。
  • {action} 为 awk 命令,可以是单个命令,也可以多个命令。整个 action(包括里面的所有命令)都必须放在{  }之间。
  • Input-file 即为要处理的文件

    举例

# awk -F: 'BEGIN{print"-----header-----"} {print $1,$7} END{print"-----footer-----"}' /etc/passwd

三、awk 程序结构(BEGIN,Body,END)区域

        1. BEGIN 区域
Begin 区域的语法:
BEGIN { awk-commands }
BEGIN 区域的命令只最开始、在 awk 执行 body 区域命令之前执行一次。

  •  BEGIN 区域很适合用来打印报文头部信息,以及用来初始化变量。
  •  BEGIN 区域可以有一个或多个 awk 命令
  •  关键字 BEGIN 必须要用大写
  •  BEGIN 区域是可选的

    2. body 区域

body 区域的语法:
/pattern/ {action}
body 区域的命令每次从输入文件读取一行就会执行一次

  •  如果输入文件有 10 行,那 body 区域的命令就会执行 10 次(每行执行一次)
  •  Body 区域没有用任何关键字表示,只有用正则模式和命令。
  • Body 区域是可选的

  • 3. END 区域

END 区域的语法:
END { awk-commands }
END 区域在 awk 执行完所有操作后执行,并且只执行一次

  •  END 区域很适合打印报文结尾信息,以及做一些清理动作
  •  END 区域可以有一个或多个 awk 命令
  •  关键字 END 必须要用大写
  •  END 区域是可选的

提示:如果命令很长,即可以放到单行执行,也可以用\折成多行执行。

四、awk 内置变量

FS表示当前的列分隔符
RS表示当前的行分隔符
OFS输出字段分隔符
ORS输出记录分隔符
NR表示当前文件的行数
NF表示当前文件有几列
FILENAME当前处理的文件名
FNR也是读取文件的行数,但是和NR 不同的是当读取的文件有两个或两个以上时,NR 读取完一个文件,行数继续增加 而FNR 重新从1开始记录

FS         

 用内置变量FS来表示分隔符,就要写在BEGIN区域里;

当遇到一个包含多个字段分隔符的文件时,不必担心,FS 可以搞定。你可以使用正则表达 式来指定多个字段分隔符,如 FS = “[,:%]” 指定字段分隔符可以是逗号 ,或者分号 : 或者百 分号 %。

创建文件:

#vi employee-multiple-fs.txt

101,John Doe:CEO%10000

102,Jason Smith:IT Manager%5000

103,Raj Reddy:Sysadmin%4500

104,Anand Ram:Developer%4500

105,Jane Miller:Sales Manager%3000

因此,下面的例子将打印 employee-multiple-fs.txt 文件中雇员名称和职位.

#awk 'BEGIN {FS="[,:%]"}{print $2,$3}' employee-multiple-fs.txt 

John Doe CEO
Jason Smith IT Manager
Raj Reddy Sysadmin
Anand Ram Developer
Jane Miller Sales Manager

# awk 'BEGIN{FS=":"}  {printf"%-20s %-2s %-2s %-2s\n", $1,$2,$3,$7}' /etc/passwd   

RS

        输入行分隔符,判断输入部分的行的起始位置,默认是换行符

awk 'BEGIN{RS=","}{print}' test4

         这里说明一下,RS=“,”将以,为分割当作一行,即a,b a被当作一行,b也被当作一行,但是细心的会发现以“,”分割c和d之间是没有“,“的为什么也当作一行了呢,是因为输入中c后面还有一个换行符\n 即,输入应该是a,b,c\n只不过\n我们看不到,输入中,a一行,b一行,c\nd一行但是输出的时候系统会将\n视为换行符,所以看上去c和d是两行,实际上是一行
        (转载于CSDN博主「昨天丶今天丶明天」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
          原文链接:https://blog.csdn.net/qq_41673534/article/details/80252016)


ORS

        输出行分割符,默认的是换行符,它的机制和OFS机制一样,对输出格式有要求时,可以进行格式化输出;
 

# awk 'BEGIN{ORS=","}{print}' test4

全部的分割符,都变成了" ,"   ,具体的格式,可以根据实际需求,进行多种变化。 


FILENAME

        想要读取当前输入文件的名称;

# awk '{ print FILENAME }' /etc/passwd

 (因为awk Body区域 的命令每读一行就会执行一次,所以会出现很多行)


OFS

        来指定一个用于输出的字段分隔符,它会定义如何使用指定的字符分隔输出字段;在下面的例子中相当于先指定分隔符为 : ,再用 ==> 来替代它;

# awk -F':' ' BEGIN { OFS="==>" ;} { print $1, $4 ;}' /etc/passwd


NF

        统计当前行的字段数;

# awk -F":" '{ print FILENAME,NR,NF }' /etc/passwd

 没指定分隔符,那么默认分隔符为空格;

$NF与NF的区别

NF 表示的是浏览记录的域的个数
$NF 表示的最后一个Field(列),即输出最后一个字段的内容;

举例:

以 : 为间隔符,输出文件的列数,又因为awk是每读取一行就执行一次命令,所以最终效果就是有很多行7。

NR

        打印行号;

# awk -F: 'NR=="1" {print $1,$3,$7}' /etc/passwd


(NR=="1"  表示打印第一行)

# awk -F: ' {print NR, $1,$3,$7}' /etc/passwd

(在print后面输入NR,表示打印行号)


FNR

        也是读取文件的行数,但是和NR 不同的是当读取的文件有两个或两个以上时,NR 读取完一个文件,行数继续增加 而FNR 重新从1开始记录

# awk '{print "NR:" NR "FNR:" FNR}' 1 2 3

五、过滤

==:
!=
>
<
>=
<=
$1~$N  代表每一个列的字段
$0        代表整行内容
~          表示匹配
!~         表示不匹配
/partrn/ 字符匹配


$0


~

六、awk输出格式

%d 整数
%s 字符串
%f 浮点数
\n 换行符
\t 制表符 tab
printf 格式化输出
print


%s字符串

%8s 表示输出8个字符的字符串, 不够8个字符右对齐。 

%-8s 表示输出8个字符的字符串, 为左对齐。

 


以绝对宽度打印字符串
通过之前的例子可以知道,如果字符串长度超过指定的宽度,字符串仍然会整个被打印出来。

# awk 'BEGIN { printf "%6s\n", "Good Boy!" }'

Good Boy! 


如果要最多打印 6 个字符,要在指定宽度的数字前面加一个小数点,即使用”%.6s”代替”%6s”,
这样即使字符串比指定宽度长,也只打印字符串中的前 6 个字符。

# awk 'BEGIN { printf "%.6s\n", "Good Boy!" }'

Good B
这个例子并非适用于所有版本的 awk,在 GAWK 3.1.5 上可以,但在 GAWK 3.1.7 上则不行。
当然,以绝对宽度打印字符串,最可取的方法是使用 substr 函数

# awk 'BEGIN { printf "%6s\n", substr("Good Boy!",1,6) }'

【1,6表示从第一个字符开始一共输出6个字符】

Good B


控制精度
数字前面的点,用来指定其数值精度。


只过滤第一字段为root的行

 注意!!==为等于的意思,=是赋值的意思,如果写成了=,那么结果如下所示:

# awk -F: '$1="root"{printf"%-20s %-2s %-2s %-2s\n", $1,$2,$3,$7}' /etc/passwd


&&符号

# awk -F: '$1!="root" && $3=="3" {printf"%-20s %-2s %-2s %-2s\n", $1,$2,$3,$7}' /etc/passwd

七、awk编程语句

条件语句

循环语句

数组


条件语句if

if(条件) command;else if(条件) command; else command 

# awk -F':' '{if($1=="root") print "The user is ROOT" > "root.file"}' /etc/passwd

(如果满足条件,就打印The user is ROOT到root.file文件中)


awk -F":" '{if($3<1000) print > "little.txt";else if($3>1000 && $3<1500) print > "middle.txt";else print > "big.txt"}' /etc/passwd

注意:在使用多个谈条件语句的时候,每写完一句。必须使用 ;  分隔开;

           并且使用文件的时候,必须加上英文双引号;

           使用且逻辑运算时要使用 &&;

做数据统计

# awk 'NR!=1 {sum+=sum+$5} END{print sum}' awk.file

(除去awk.file的第一行,【默认分隔符是空格】将该文件的第五列相加,并且输出到标准输出)


变量

用数组统计第六列 

# ps aux |awk 'NR!=1 {a[$1]+=$6} END{for( i in a) print i,a[i]}'

八、awk函数

length(s)    返回字符串s的长度

split()         分割字符串

tolower      该字段全部小写

toupper     该字段全部小写


length(s)

# awk -F':' '{if(length($1)>=4) print NR, "第一列数字段长度大于四的" > "root.file"}' /etc/passwd


(将/etc/passwd文件中以 : 为分隔符的第一个字段,如果该字段长度>=4,那么输出该行的行号并且输出“第一列数字段长度大于四的”到root.file文件中)


toupper     

# awk -F':' '{if(length($1)>=4) print NR,toupper($7)}' /etc/passwd


 tolower

# awk -F' ' '{if(length($1)>=4) print NR,tolower($3)}' sed.file

九、printf 按照某一格式化输出文件

# vi score.file
HCL 100 110 119
hcl 100 159 516


# vi score.call


#! /bin/awk -f
BEGIN{
 Chinese=0
 Math=0
 English=0
 printf"NAME  Chinese  Math  English  Total\n"
 printf"--------------------------------------------------\n"
}
{
 Chinese+=$2
 Math+=$3
 English+=$4
 printf"%-7s %-7d %-7d %-7d %-7d\n", $1,$2,$3,$4,$2+$3+$4
}
END{
 print"---------------------------------------------------\n"
 printf"Total:  %-6d %-6d %-6d\n", Chinese,Math,English
 printf"AGE:   %7.2f,%7.2f,%7.2f\n",Chinese/NR,Math/NR,English/NR
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LKsTaRt~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值