13.shell awk基础

awk是一种强大的文本处理工具,主要用于对文本和数据进行处理。

awk作用
awk命令擅长对文件列进行操作 (awk在识别列信息的时候,默认以空格为分隔符,来识别列信息的)
awk命令擅长对数据文件进行分析
awk命令可以编写脚本
awk可以进行算术运算

awk语法结构
awk options 'pattern {action}' file
awk 选项     '模式{动作}'        文件

options:是一些选项,用于控制 awk 的行为。

-F : 指定输入字段的分隔符,默认是空格。使用这个选项可以指定不同于默认分隔符的字段分隔符。
-v  :设置 awk 内部的变量值。可以使用该选项将值传递给 awk 脚本中的变量。
-f : 指定一个包含 awk 脚本的文件。这样可以在文件中编写较大的 awk 脚本,然后使用 -f 将其加载。

pattern:是用于匹配输入数据的模式。如果省略,则 awk 将对所有行进行操作。
{action}:是在匹配到模式的行上执行的动作。如果省略,则默认动作是打印整行。


awk 'BEGIN {命令} pattern {命令} END {命令}' 文件

BEGIN:处理文件前执行的动作
END:处理文件后执行的动作
pattern:模式,每一行都执行的动作
BEGIN和END里的命令只是执行一次,pattern里的命令会匹配每一行去处理


awk脚本结构
vim test.awk

#处理文件前执行的动作
BEGIN {
    printf "--------\n"  #这里面放的是执行前的语句
}
#处理文件的过程中
{    
    printf "----------\n" #这里面放的是处理每一行时要执行的语句
}
#文件处理完后执行的动作
END {
    printf "-----------\n" #这里面放的是处理完所有的行后要执行的语句
}

脚本执行

awk -f test.awk 要处理的文件

awk工作原理

逐行读取信息
判断是否为需要的信息
如果是满足条件的信息,就对满足条件的信息做相应的处理
如果不是满足条件的信息,就会继续读取下一行信息

以该命令为例: awk -F: ‘{print $1,$3}’ /etc/passwd

  1.awk将文件中的每一行作为输入, 并将每一行赋给内部变量$0, 以换行符结束 
  2.awk开始进行字段分解,每个字段存储在已编号的变量中,从$1开始[默认空格分割] 
  3.awk默认字段分隔符是由内部FS变量来确定, 可以使用-F修订 
  4.awk行处理时使用了print函数打印分割后的字段 
  5.awk在打印后的字段加上空格,因为$1,$3 之间有一个逗号。逗号被映射至OFS内部变量中,称为输出字段分隔符, OFS默认为空格. 
  6.awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕.

在这里插入图片描述


awk内部变量
内置变量含义
$0整行内容
$1-$n当前行的第1-n个字段
NF当前行的字段个数,也就是多少列
NR当前的行号,从1开始计数
FS输入字段分隔符。不指定默认以空格或tab键分割
RS输入行分隔符。默认回车换行
OFS输出字段分隔符。默认为空格
ORS输出行分隔符。默认为回车换行

测试文件准备

cat awk_test.txt

ll 1990 50 51 61
kk 1991 60 52 62
hh 1992 70 53 63
jj 1993 80 54 64
mm 1994 90 55 65

1.awk内置变量,$0保存当前记录的内容
awk '{print $0}' awk_test.txt
在这里插入图片描述

2.awk内置变量,FS指定字段分割符,默认以空白行作为分隔符
awk '{print $1}' awk_test.txt
在这里插入图片描述

FS指定字段分割符
awk -F '[: ]+' '{print $1}' awk_test.txt
在这里插入图片描述

3.awk内置变量NF,保存每行的最后一列
awk '{print NF,$NF}' awk_test.txt
打印NF和$NF
NF 当前行有多少列
$NF 最后一列内容
在这里插入图片描述

4.awk内置变量NR,表示记录行号。
awk '{print NR,$0}' awk_test.txt
在这里插入图片描述

如果想打印第二行到第三行的内容怎么办?
awk 'NR>1&&NR<4 {print NR,$0}' awk_test.txt
在这里插入图片描述

如果既想打印第三行,又想打印第一列?
awk 'NR==3 {print $1}' awk_test.txt
在这里插入图片描述

5.awk内置变量RS,输入行分隔符。
awk 'BEGIN{RS="--"} {print $0}' awk-test.txt
默认以换行为行分隔符,这里指定了 ‘–’ 为行分隔符,原本一行的内容,分为了三行。
在这里插入图片描述

6.awk内置变量,“OFS输出字段分隔符”,初始情况下OFS变量是空格。
awk 'BEGIN{RS="--";FS="|";OFS=": "} {print $1,$2}' awk-test.txt
以–为行分隔符,以|为输入字段分隔符,输出的内容将以:为分隔符展示
在这里插入图片描述

7.awk内置变量,“ORS输出行分隔符”,默认行分割符为\n
awk 'BEGIN{RS="--";FS="|";OFS=": ";ORS="*****"} {print $1,$3}' awk-test.txt
在这里插入图片描述


awk格式输出

awk可以通过printf函数生成非常漂亮的数据报表。

格式符含义
%s打印字符串
%d打印十进制数(整数)
%f打印一个浮点数(小数)
%x打印十六进制数
修饰符含义
-左对齐
+右对齐

printf默认没有分隔符,输出是一坨

awk 'BEGIN{FS=":"} {printf $1}' passwd

在这里插入图片描述

2.加入换行,格式化输出。
awk 'BEGIN{FS=":"} {printf "%s\n",$1}' passwd
在这里插入图片描述

3.使用占位符美化输出。
awk 'BEGIN{FS=":"} {printf "%20s %20s\n",$1,$7}' passwd
在这里插入图片描述

4.默认右对齐,-表示左对齐。
awk -F":" '{printf "%-20s %-20s\n",$1,$7}' passwd
在这里插入图片描述


zhangsan	80	90	82	75
lisi		91	76	97	98
wangwu		86	98	89	97
oldsix		87	99	78	99
sun			76	96	85	69
BEGIN { #行处理前
	printf "%-20s %-20s %-20s %-20s %-20s \n",
	"Name","Chinese","Math","PE","Engilsh"
}
{ #行处理中
	printf "%-20s %-20s %-20s %-20s %-20s \n",
	$1,$2,$3,$4,$5
}

在这里插入图片描述


awk模式匹配

awk第一种模式匹配:RegExp
awk第二种模式匹配:关系运算匹配

RegExp示例

1.匹配/etc/passwd文件行中含有root字符串的所有行。
awk -F":" '/root/{print $0}' passwd

在这里插入图片描述

2.匹配/etc/passwd文件行中以root开头的行。
awk '/^root/' passwd
在这里插入图片描述

3.匹配/etc/passwd文件行中/bin/bash结尾的行。
awk '/\/bin\/bash$/' passwd
在这里插入图片描述


运算符匹配示例
符号含义
<小于
>大于
<=小于等于
>=大于等于
==等于
!=不等于
~匹配正则表达式
!~不匹配正则表达式

1、以:为分隔符,匹配/etc/passwd文件中第3个字段小于50的所有行信息
awk -F":" '$3<50{print $0}' passwd
在这里插入图片描述

2、以:为分隔符,匹配/etc/passwd文件中第7个字段为/bin/bash的所有行信息
awk -F":" '$7=="/bin/bash" {print $0}' passwd
在这里插入图片描述

3、以:为分隔符,匹配/etc/passwd文件中第7个字段不为/bin/bash的所有行信息
awk -F":" '$7!="/bin/bash" {print $0}' passwd
在这里插入图片描述

4、以:为分隔符,匹配/etc/passwd文件中第3个字段包含3个数字以上的所有行信息
awk -F":" '$3~/[0-9]{3,}/{print $0}' passwd
在这里插入图片描述


布尔运算符匹配示例
符号含义
||
&&

1、以:为分隔符,匹配passwd文件中包含ftp或mail的所有行信息
awk -F":" '/ftp/||/mail/ {print $0}' passwd
在这里插入图片描述

2、以:为分隔符,匹配passwd文件中第3个字段小于50并且第4个字段大于50的所有行信息
awk -F":" '$3<50&&$4>50 {print $0}' passwd
在这里插入图片描述
3.匹配没有/sbin/nologin的行。
awk -F":" '$0 !~ /\/sbin\/nologin$/ {print $0}' passwd
在这里插入图片描述


运算符匹配示例
运算符han yi
+
-
*
/
%模(取余)

1、计算学科平均分数

zhangsan	80	90	82	75
lisi		91	76	97	98
wangwu		86	98	89	97
oldsix		87	99	78	99
sun			76	96	85	69

vim grades.awk

BEGIN {
	printf "%-20s %-20s %-20s %-20s %-20s %-20s \n",
	"Name","Chinese","Math","PE","Engilsh","AVG"
}
{
	sum=$2+$3+$4+$5
	avg=sum/(NF-1)
}

{
	printf "%-20s %-20s %-20s %-20s %-20s %-20s \n",
	$1,$2,$3,$4,$5,avg
}

awk -f grades.awk grades.txt

在这里插入图片描述

核对一下平均分
echo " 80 90 82 75" |xargs |sed 's# #+#g'|bc

在这里插入图片描述
在这里插入图片描述


awk条件判断
if判断

if语句格式:{if(表达式) {语句;语句;....}}

1.以:为分隔符,打印当前管理员用户名称
在这里插入图片描述

BEGIN {
	FS=":"
}
{
	if($3==0){
		print $1,"is administrator"
		}
}

2.以:为分隔符,统计系统用户数量
在这里插入图片描述

BEGIN{ #行处理前
	FS=":"
}
{ #行处理中
	if($3>0 && $3<1000){
		i++
	}
}
END{ #行处理后
	print "系统用户数量为:"i
}

3.以:为分隔符,统计普通用户数量
在这里插入图片描述

BEGIN{
	FS=":"
}
{
	if($3>1000){
		i++
	}
}
END{
	print "普通用户数量为:"i
}

4.以:为分隔符,只打印passwd中第3个字段的数值在50-100范围内的行信息
awk 'BEGIN{FS=":"}{if($3>50 && $3<100){print $0}}' passwd

在这里插入图片描述

BEGIN{
	FS=":"
}
{
	if ($3>50 && $3<100){
		print $0
	}
}

日常使用中更推荐awk脚本的形式,方便阅读,可持续使用,命令行的形式无法重复使用。


if...else语句格式:{if(表达式) {语句;语句;...} else{语句;语句;...}}

1.以:为分隔符,判断第三列如果等于0,则打印该用户名称,如果不等于0则打印第七列。

awk 'BEGIN{FS=":"}{if($3==0){print $1}else{print $7}}' passwd

BEGIN{
	FS=":"
}
{
	if($3==0){
		print $1
	}
	else{
		print $7
	}
}

在这里插入图片描述

2、以:为分隔符、判断第三列如果等于0,则打印管理员出现的个数,否则都视为系统用户,并打印它的个数。

awk 'BEGIN{FS=":";OFS="\n"} {if($3==0){i++} else{j++}} END{print i "管理员",j "系统用户" }' passwd

BEGIN{
	FS=":"
	OFS="\n"
}
{
	if($3==0){
	i++
	}
	else{
	j++
	}
}
END{
	print  i "管理员",j "系统用户"
}

在这里插入图片描述


if...else语句格式:{if(表达式1) {语句;语句;...} else if(表达式2){语句;语句;...} else{语句;语句;...}}

1.使用awk 打印出当前/etc/passwd文件管理员有多少个,系统用户有多少个,普通用户有多少个

BEGIN{
	FS=":"
	OFS="\n"
}
{
	if($3==0){
	i++
	}
	else if($3>0 && $3<1000 ){
	j++
	}
	else {
	k++
	}
}
END{
	print  i "管理员",j "系统用户",k "普通用户"
}

在这里插入图片描述


2.打印/etc/passwd文件中UID小于50的、或者UID大于50小于100、或者UID大于100的用户名以及UID。

在这里插入图片描述
在这里插入图片描述

BEGIN{
	FS=":"
	printf "%-20s %-20s %-20s \n","UID区间","用户名","UID"
}
{
	if($3<50){
	i++
	 printf "%-20s %-20s %-20s \n","UID<50",$1,$3
	}
	else if($3>50&&$3<100){
	j++
	 printf "%-20s %-20s %-20s \n","50<UID<100",$1,$3
	}
	else {
	k++
	printf "%-20s %-20s %-20s \n","100<UID",$1,$3
	}
}
END{

	print "UID<50 :"i,"50<UID<100 :"j,"100<UID :"k
}


awk循环语句
while循环

while (条件表达式)动作

1.打印1-9

awk 'BEGIN{i=1;while(i<10){print i;i++}}'

在这里插入图片描述

2.打印passwd文件的每一行中的每一列

 awk -F":" '{i=1;while(i<=NF){print $i;i++}}' passwd

在这里插入图片描述


for循环

for(初始化计数器;计数器测试;计数器变更)动作

1.遍历1-4

awk 'BEGIN{for(i=1;i<5;i++){print i}}'

在这里插入图片描述

2.每行打印10次

awk -F":" '{for(i=1;i<=10;i++){print $0}}' passwd

在这里插入图片描述

3.打印每一行每一列

awk -F":" '{for(i=1;i<=NF;i++){print $i}}' passwd

在这里插入图片描述

4.计算1+2+3+4+…+100的和,请使用while、for两种循环方式实现

shell

#!/bin/bash

for i in {1..100}
do
	sum=$[$sum+$i]   #或 let sum+=i
done
	echo $sum

在这里插入图片描述


while循环:
awk 'BEGIN{i=1;while(i<=100){sum+=i;i++} {print sum}}'

BEGIN{
	while (i<=100){
	sum+=i
	i++
	}
	print sum
}

在这里插入图片描述


for循环:
awk 'BEGIN{for(i=1;i<=100;i++){sum+=i}print sum}'

BEGIN{
	for(i=1;i<=100;i++){
		sum+=i
	}
		print sum
}

在这里插入图片描述

  • 27
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值