当前位置:首页 > Liunx > 正文内容

shell三剑客之awk-07

邓鹏10个月前 (01-13)Liunx225

awk介绍

grep,sed,awk为linux的文件处理“三剑客”,各有特长。

grep:更适合单纯的==查找==(通过要查找的关键字)或匹配(通过正则)==行==

sed:更适合==编辑==文本(行删除,行打印,行增加,替换与修改等)

awk:更适合==格式化文本,对文本进行较复杂格式处理==

今天主要讨论awk,格式化文本是很专业的说法,通俗来说就是可以把文本变成你想要的样子

awk使用格式

awk -F"分隔符" "命令动作" 被处理的文件,"也可以正则匹配" 正则匹配到的内容算一个分隔符也可以通过管道传给awk处理cat 被处理的文件 | awk -F"分隔符" "命令动作"

awk内部相关变量


常用变量

说明

$0 (==常用==)

当前处理行的所有记录(所有列数之和,包括分隔符)

$1 到 $n (==常用==)


文件中每行以间隔符号分割的不同字段($1代表第1列。。。。。。以此类推)

NF (==常用==)

当前记录的字段数(列数)

$NF (==常用==)

最后一列

NR (==常用==)

行号

FS (==常用==)

定义间隔符,等同于-F参数

awk的行匹配符

awk行匹配符

说明


==

等于,完全匹配

~

匹配

!=

不等于,不完全匹配

!~

不匹配


awk中BEGIN...END结构

在前面我们有提过awk在处理文件时是逐行处理的,那么有可能要在处理第一行前做一些事情(比如定义变量),在处理完最后一行后做一些事情(比如打印统计信息等)。这就要用到BEGIN...END结构了。

结构关键字


BEGIN { }

在awk处理文件第一行之==前==,大括号里写处理前的代码

{ }

前面没有BEGIN或END的大括号,都表示逐行处理文件过程==中==要做的事,==会根据行数来循环==

END { }

在awk处理完了后一行之==后==,大括号里写处理前的代码

**问题:** 比较这两句, 结果有什么区别?(请先根据理解在脑海里想一个答案的样子,再执行命令比较一下)
# head -3 /etc/passwd | awk -F: '{print "用户名\tUID"}{print $1"\t"$3}'                   #每行都会执行两个括号内的代码
# head -3 /etc/passwd | awk -F: 'BEGIN {print "用户名\tUID"}{print $1"\t"$3}'         #以BEGIN开头的括号内代码,只在开始执行一次。


对标上述BEGIN和END理解一下,BEGIN只在开始的时候执行一次,END只在结尾的时候执行一下,大括号{}每处理一行 都是执行一次内部代码,其中$1$2 等就是当行截取的第一列及第二列的值
# cat /etc/sysconfig/network |wc -l
2									此文件有2行

# awk -F: 'BEGIN {print "aaa"} {print "bbb"} END {print "ccc"}' /etc/sysconfig/network
aaa
bbb
bbb
ccc

思路

  • 一定要牢记awk是会逐行处理文件,所以直接看作是按行数来处理的循环

  • 在循环前定义一个变量表示要计算的总列数,如sum=0

  • 每行循环处理时,sum=sum+每行的列数(再次强调,awk里的运算不需要运算符)

  • 循环处理完文件后,打印出sum的值就是想要求的总列数了

  • 也就是说awk的处理方式就是类似下面的这个循环结构

sum=0
for i in 行数
do
	sum=sum+每一行的列数
done
echo sum

awk的运算符

再次强调,awk是一门语言,所以有自己的运算符(注意:有些地方与shell不一样)

运算符

说明

==

等于 和shell里不一样,shell里字符串比较是= ;数字比较是-eq

!=

不等于 shell里数字比较是-ne代表不等于

>

大于 shell里数字比较是(-gt)代表大于

<

小于 shell里数字比较是(-lt)代表小于

>=

大于等于 shell里数字比较是(-ge)代表大于等于

<=

小于等于 shell里数字比较是(-le)代表小于等于

&&

逻辑与(和)

||

逻辑或

+

加法

-

减法

*

乘法

/

除法

%

求余数

打印/etc/passwd第五行(**可以把NR==5看作是一个判断的条件,满足此条件才执行print $0**)
awk 'NR==5 {print $0}' /etc/passwd

打印/etc/passwd第五到十行,并在前面加上行号
awk 'NR>=5 && NR<=10 {print NR,$0}' /etc/passwd

打印第五行和第六行
awk -F: 'NR==5 || NR==6 {print $0}' /etc/passwd

打印/etc/passwd奇数行 (删除偶数行)
awk 'NR%2==1 {print NR,$0}' /etc/passwd

打印/etc/passwd偶数行 (删除奇数行)
awk 'NR%2==0 {print NR,$0}' /etc/passwd

对/etc/passwd里的用户做分类,分成管理员,系统用户,普通用户

# awk -F: '$3==0 {print $1}' /etc/passwd

# awk -F: '$3<500 && $3>0 || $3==65534  {print $1}' /etc/passwd

# awk -F: '$3>499 && $3!=65534 {print $1}' /etc/passwd

awk总体语法格式

#比如: 将/etc/passwd文件的前三行处理成下面的样子(先不要管它是怎么得到的,我们慢慢来讲解)
# head -3 /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
# head -3 /etc/passwd |awk -F: 'BEGIN{print"用户名\tUID"}{print $1"\t"$3}'
用户名  UID
root    0
bin     1
daemon  2

# head -3 /etc/passwd |awk -F: '{print $1}'
root
bin
daemon

# head -3 /etc/passwd |awk -F: '{print $3}'
0
1
2

#awk可以将文本截取多段后自由拼接,并可以额外加字符进行粘合,而cut会比较麻烦
# head -3 /etc/passwd |awk -F":" '{print $1"用户的uid是"$3}'
root用户的uid是0
bin用户的uid是1
daemon用户的uid是2

#而cut要实现同类效果会比较麻烦,cut命令无法在截取的两列中间直接加字符进行粘合,需要脚本
#!/bin/bash

head -3 /etc/passwd | cut -d: -f1,3 |while read a
do
        head=`echo $a|cut -d: -f1`
        tail=`echo $a|cut -d: -f2`
        echo  "$head的uid是$tail"
done

以逗号或点号为分隔符(再次回顾正则表达式里中括号里的字符任选其一),截取第2列
# echo hello,world.sed |awk -F[,.] '{print $2}'
world


以逗号或点号为分隔符,将三列重新排序,表示遇到, . 都算作一个分割。
# echo hello,world.sed |awk -F[,.] '{print $2","$3"."$1}'
world,sed.hello

下面这样的字符串,以点为分隔符可以做,但是点号太多,不好数.所以可以用正则表达式,以连续的多个点来为分隔符 [.]+ 表示分隔符为至少一个点或者连续多个点为分隔符
# echo "haha,hehe..............................heihei......" |awk -F"[.]+" '{print $2}'
heihei


截取/etc/passwd文件的最后一列
# awk -F: '{print $NF}' /etc/passwd

截取/etc/passwd文件的倒数第二列
# awk -F: '{print $(NF-1)}' /etc/passwd


#awk也可以做行匹配,$0代表每一行所有内容~代表匹配每一行是否包含root,如果包含就把这一行打印出来
awk '$0~"root" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin


#完全匹配
查找/etc/passwd文件里用户名为root的行
awk -F: '$1=="root" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash

#匹配
查找/etc/passwd文件里用户名里有oo这两个字符的行
awk -F: '$1~"oo" {print $0}' /etc/passwd

#不完全匹配
查找/etc/passwd文件里用户名不为root的行
awk -F: '$1!="root" {print $0}' /etc/passwd

#不匹配
awk -F: '$1!~"oo" {print $0}' /etc/passwd


扫描二维码推送至手机访问

版权声明:本文由PowerShell中文社区发布,如需转载请注明出处。

本文链接:https://www.powershell.com.cn/?id=34

分享给朋友:

“shell三剑客之awk-07” 的相关文章

Shell脚本介绍

Shell脚本介绍

今日目标了解Shell脚本概念磁盘相关命令回顾:磁盘相关命令说明fdisk分msdos分区与要看系统硬盘与分区情况lsblk查看块设备与其挂载情况df -h查看已经挂载的文件系统情况mount也是查看挂载的情况,还能看到挂载的参数(ro或rw等)iostat需要安装sysstat软件包,动态查看磁盘...

shell变量说明-01

shell变量说明-01

变量介绍什么是变量?通俗的说, 变量就是用来临时保存数据的。(注: 学python时会将变量讲得更深入)变量定义的格式==变量名=变量值==想要得到变量的值,在变量前加$符号# a=1 # echo $a 1什么时候需要定义变量?如果某个内容需要多次使用,并且在代码...

Liunx定时计划任务配置说明

Liunx定时计划任务配置说明

在 Linux 中,* 代表通配符,用于表示任意值。在 cron 任务中,* 可以用来指定分钟、小时、日期等时间单位的取值。具体而言,cron 表达式由五个时间字段组成,分别表示分钟(0-59)、小时(0-23)、日期(1-31)、月份(1-12)和星期几(0-7,其中0和7都表示星期日)。这些时间...

CentOS7 服务器上使用T4显卡部署大型AI模型的详细教程

CentOS7 服务器上使用T4显卡部署大型AI模型的详细教程

环境准备服务器配置CPU:Platinum8225c 显卡T4 GPU:T4 16GB  CPU:8核 内存32GB操作系统:Centos7.6英伟达显卡驱动Docker容器环境Docker使用的NVIDIA驱动Ollama容器镜像,Ollama支持的显卡型号:点击查看查看运行环境的资源使...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。