Shell脚本之awk篇

Shell脚本之awk篇
目录:
一、概述
二、awk基本语法格式
三、awk基本操作
四、awk条件及循环语句
五、awk函数
六、awk演示示例(源自于man手册)

一、概述
1. 产品概述:
awk是一种编程语言,用于在linux/unix下对文本和数据进行扫描与处理。数据可以来自标准输入、文件、管道。
awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Peter Weinberger、Brian Kernighan。
实际上awk有很多种版本,如:awk、nawk、mawk、gawk、MKS awk、tawk... 这其中有开源产品也有商业产品。
目前在Linux中常用的awk编译器版本有mawk,gawk,其中以RedHat为代表使用的是gawk,以Ubuntu为代表使用的是mawk。
gawk是GNU Project 的awk解释器的开源代码实现。
本文将以gawk作为讲解工具。
2. 原理:
1). awk逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行你想要的操作。
2). awk基本结构包括模式匹配(用于找到要处理的行)和处理过程(即处理动作)。
pattern {action}
# 提示:awk读取文件内容的每一行时,将对比改行是否与给定的模式相匹配,如果匹配则执行处理过程,否则对该行不做任何处理。
如果没有指定处理脚本,则把匹配的行显示到标准输出,即默认处理动作是print打印行;
如果没有指定模式匹配,则默认匹配所有数据。
3). awk有两个特殊的模式:BEGIN和END,他们被放置在没有读取任何数据之前以及在所有数据读取完成以后执行。
3. awk流程图:
awk流程
提示:awk将文件中的每一行当作一条记录,并将记录分割为若干字段,默认以空格或制表符为分隔符。
如This is a test file. 将分割为5个字段,awk可以对这5个字段进行分别处理。

二、awk基本语法格式
1. 格式:
gawk [ POSIX or GNU style options ] -f program-file [ -- ] file ...
注释:POSIX or GNU style options表示gawk支持POSIX以及GNU两种选项;-f后接脚本文件;file表示准备处理的文档名称。
2. gawk支持以下选项:
-F fs
--field-separator fs
指定以fs作为输入行的分隔符(默认分隔符为空格或制表符)
-v var=val
--assign var=val
在执行处理过程以前,设置一个变量var值为val
-f program-file
--file program-file
从脚本文件中读取AWK指令,以取代在命令参数中输入处理脚本
-W compat
-W traditional
--compat
--traditional
使用兼容模式运行awk,GNU扩展选项将被忽略
-W copyleft
-W copyright
--copyleft
--copyright
输出简短的GNU版权信息
-W dump-variables[=file]
--dump-variables[=file]
打印全局变量(变量名、类型、值)到文件中,如果没有提供文件名,则自动输出至名为dump-variables的文件中。
示例:[jacob@localhost ~]# awk -W dump-variables=out.txt 'x=1 {print x}' test.txt
-W exec file
--exec file
类似于-f选项,但脚本文件需要以#!开头;另外命令行的变量将不再生效
-W help
-W usage
--help
--usage
显示各个选项的简短描述
3. awk程序结构
一个awk程序包含一系列的 模式 {动作指令} 或是函数定义。
模式可以是:
BEGIN
END
表达式
表达式,表达式
动作指令需要以{}引起来
4. 简单示例:
[jacob@localhost ~]# awk '/^$/ {print "Blank line}' test.txt
备注:/^$/通过正则表达式匹配空白行,动作为打印Blank line;即test.txt如有N个空白行,awk将在屏幕打印N个Blank line。
[jacob@localhost ~]# awk '/HOSTNAME/' /etc/sysconfig/network
备注:打印包含主机名的行,因为没有指定动作指令,默认动作为打印。
[jacob@localhost ~]# cat awk.sh
'/^$/ {print "Blank line}'
[jacob@localhost ~]# awk -f awk.sh test.txt
备注:提前编辑一个awk脚本再通过-f选项调用该脚本。

三、awk基本操作
1. 记录与字段
awk一次从文件中读取一条记录,并将记录存储在字段变量$0中。记录被分割为字段并存储在$1,$2 ..., $NF中(默认使用空格或制表符为分隔符)。
内建变量NF为记录的字段个数
示例:
[jacob@localhost ~]# echo hello the world |
>awk '{print $1,$2,$3}'
备注:读取输入行并输出第一个字段,第二个字段,第三个字段。
[jacob@localhost ~]# echo hello the world |
>awk '{print $0}'
备注:读取输入行并输出该行。
[jacob@localhost ~]# echo hello the world |
>awk '{print NF}'
备注:读取输入行并输出该行的字段个数:3个字段。
[jacob@localhost ~]# echo hello the world |
>awk '{print $NF}'
备注:读取输入行并输出该行的第三个字段,因为NF为3,所以$NF等同于取行的最后一个字段。
2. 字段分隔符
默认awk读取数据以空格或制表符作为分隔符,但可以通过-F或FS(field separator)变量来改变分隔符。
示例:
[jacob@localhost ~]# awk -F: '{print $1}' /etc/passwd
[jacob@localhost ~]# awk 'BEGIN {FS = ":"} {print $1}' /etc/passwd
备注:以上两个示例均将字段的分隔符改冒号(:),即以冒号为分隔符打印passwd文件的第一个字段(帐号名称)。
注意:如果使用FS改变分隔符的话,需要在BEGIN处定义FS,因为在读取第一行前就需要改变字段分隔符。
进阶:指定多个字段分隔符(文档内容为:hello the:word,!)
[jacob@localhost ~]# echo 'hello the:word,!' |
>awk 'BEGIN {FS="[:, ]"} {print $1,$2,$3,$4}'
3. 内置变量
以下为awk内置变量:
ARGC 命令行参数个数
FILENAME 当前输入文档的名称
FNR 当前输入文档的当前记录编号,尤其当有多个输入文档时有用
NR 输入流的当前记录编号
NF 当前记录的字段个数
FS 字段分隔符
OFS 输出字段分隔符,默认为空格
ORS 输出记录分隔符,默认为换行符\n
RS 输入记录分隔符,默认为换行符\n
示例:
[jacob@localhost ~]# cat test1.txt
This is a test file.
Welcome to Jacob's Class.
[jacob@localhost ~]#cat test2.txt
Hello the world.
Wow! I'm overwhelmed.
Ask for more.
[jacob@localhost ~]# awk '{print FNR}' test1.txt test2.txt
1
2
1
2
3
备注:输出当前文档的当前行编号,第一个文件两行,第二个文件三行。
[jacob@localhost ~]# awk '{print NR}' test1.txt test2.txt
1
2
3
4
5
备注:awk将两个文档作为一个整体的输入流,通过NR输入当前行编号。
[jacob@localhost ~]# awk '{print NF}' test1.txt
5
4
备注:test1.txt文档的第一行有5个字段,第二行有4个字段。
[jacob@localhost ~]# awk 'BEGIN {FS = ":"} {print $1}' /etc/passwd
[jacob@localhost ~]# awk '{print $1,$2,$3}' test1.txt
备注:默认print输出时,各参数将的输出分隔符默认为空格,所以输出内容如下
This is a
Welcome to Jacob's
[jacob@localhost ~]# awk 'BEGIN {OFS="-"} {print $1,$2,$3}' test1.txt
备注:通过OFS将输出分隔符设置为"-",这个print在输出第一、二、三个字段时,中间的分隔符为"-",结果如下
This-is-a
Welcome-to-Jacob's
[jacob@localhost ~]# cat test3.txt
mail from: tomcat@gmail.com
subject:hello
data:2012-07-12 17:00
content:Hello, The world.

mail from: jerry@gmail.com
subject:congregation
data:2012-07-12 08:31
content:Congregation to you.

mail from: jacob@gmail.com
subject:Test
data:2012-07-12 10:20
content:This is a test mail.
[jacob@localhost ~]# awk 'BEGIN {FS="\n"; RS=""} {print $3}' test3.txt
备注:读取输入数据,以空白行为记录分隔符,即第一个空白行前的内容为第一个记录,第一个记录中字段分隔符为换行符。
以上awk的效果为打印所有的邮件时间,即每个记录的第三个字段。
4. 表达式与操作符
表达式是由变量、常量、函数、正则表达式、操作符组成,awk中变量有字符变量和数字变量。如果在awk中定义的变量没有初始化,则初始值为空字串或0。
注意:字符操作时一定记得需要加引号
1) 变量定义示例:
a="welcome to beijing"
b=12
2) 操作符(awk操作符与C语言类似)
+ 加
- 减
* 乘
/ 除
% 取余
^ 幂运算
++ 自加1
-- 自减1
+= 相加后赋值给变量(x+=9等同于x=x+9)
-= 相减后赋值给变量(x-=9等同于x=x-9)
*= 相乘后赋值给变量(x*=9等同于x=x*9)
/= 相除后赋值给变量(x/=9等同于x=x/9)
> 大于
< 小于
>= 大于等于
<= 小于等于
== 等于
!= 不等于
~ 匹配
!~ 不匹配
&& 与
|| 或
操作符简单示例:
[jacob@localhost ~]# echo "test" | awk 'x=2 {print x+3}'
[jacob@localhost ~]# echo "test" | awk 'x=2,y=3 {print x*2, y*3}'
[jacob@localhost ~]# awk '/^$/ {print x+=1}' test.txt 备注:统计所有空白行
[jacob@localhost ~]# awk '/^$/ {x+=1} END {print x}' test.txt 备注:打印总空白行个数
[jacob@localhost ~]# awk -F: '$1~/root/ {print $3}' /etc/passwd 备注:打印root的ID号
[jacob@localhost ~]# awk -F: '$3>500 {print $1}' /etc/passwd 备注:列出计算机中ID号大于500的用户名

四、awk条件及循环语句
1. IF条件判断格式:
if (表达式)
动作1
else
动作2
或者if (表达式) 动作1;else 动作2
说明:如果表达式的判断结果为真则执行动作1,否则执行动作2。
示例:(判断boot分区可用容量小于20M时报警,否则显示OK)
[jacob@localhost ~]# df |grep "boot" |awk '{if($4<20000) print "Alart"; else print "OK"}'
2. 循环
while (条件)
动作
x=1
while (i < 10) {
print $i
}
示例:
[jacob@localhost ~]# awk 'i=1 {} BEGIN { while (i<=10) {++i; print i}}' test.txt

do
动作
while (条件)
示例:
[jacob@localhost ~]# awk 'BEGIN { do {++x;print x} while (x<=10)}' test.txt
for (变量;条件;计数器)
动作
示例:
for (i=1;i<=10;i++)
print i
[jacob@localhost ~]# awk 'BEGIN {for(i=1;i<=10;i++) print i}' test.txt
[jacob@localhost ~]# awk 'BEGIN {for(i=10;i>=1;i--) print i}' test.txt
说明:因为以上循环语句使用的awk均使用的BEGIN模式,所以输入文档可以为任意文档(无关紧要)。
3. Break与Continue
break 跳出循环
continue 终止当前循环
示例:
for (i=1; i<=10;i++) {
if (i=5)
continue
print i
}
说明:打印1-4,6-10
for (i=1; i<=10;i++) {
if (i=5)
break
print i
}
说明:仅打印1-4

五、函数
1. rand () 产生0-1之间的浮动类型的随机数
备注:rand产生随机数时需要通过srand()设置一个参数,否则单独的rand()每次删除的随机数都是一样的。
示例:
[jacob@localhost ~]# awk 'BEGIN {print rand(); srand(); print srand()}' test.txt
2. gsub(x,y,z) 在字串z中使用字串y替换与正则表达式x相匹配的所有字串,z默认为$0
sub(x,y,z) 在字串z中使用字串y替换与正则表达式x相匹配的第一个字串,z默认为$0
示例:
[jacob@localhost ~]# awk -F: 'gsub(/root/,"jacob",$0) {print $0}' /etc/passwd 备注:将passwd每行中所有的root修改为jacob显示至屏幕
[jacob@localhost ~]# awk -F: 'sub(/root/,"jacob",$0) {print $0}' /etc/passwd 备注:将passwd每行中第一个root修改为jacob显示至屏幕
sub相当于sed中的s///,gsub相当于sed中的s///g。
3. length(z) 返回字串z的长度
示例:
[jacob@localhost ~]# awk '{print length()}' test.txt 备注:显示test.txt文档每行的字符长度
4. gentline 从输入中读取下一行内容
示例:
[jacob@localhost ~]# df -h
Filesystem Size Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
19G 3.6G 15G 21% /
/dev/sda1 99M 14M 81M 15% /boot
tmpfs 141M 0 141M 0% /dev/shm
none 140M 104K 140M 1% /var/lib/xenstored

说明:从以上命令的输出结果可以看出,分区的剩余容量显示在第4列,但唯独/根分区的记录显示在了两行;我们需要判断当记录的字段个数为1时,读取下一行,并将该行的第3列显示至屏幕。
[jacob@localhost ~]# df -h |awk '{if(NF==1) {getline; print $3}; if(NF==6) print $4}'
[jacob@localhost ~]# df -h |awk 'BEGIN {print "Disk Free:"} {if(NF==1) {getline; print $3}; if(NF==6) print $4}'

六、awk演示示例(源自于man手册)
1. emulate cat. 模拟cat程序

{ print }

2. emulate wc. 模拟wc程序,统计行数、单词数、字符数

{ chars += length($0) + 1 # add one for the \n
words += NF
}

END{ print NR, words, chars }

3. sum the second field of every record based on the first field. 根据第一列的内容统计第二列的数据

$1 ~ /credit|gain/ { sum += $2 }
$1 ~ /debit|loss/ { sum -= $2 }

END { print sum }

4. Print and sort the login names of all users: 显示计算机帐号用户名并排序

BEGIN { FS = ":" }
{ print $1 | "sort" }


http://blog.sina.com.cn/s/blog_7b9ace5301014q8o.html
http://manual.blog.51cto.com/3300438/932958
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: awk是一种文本处理工具,常用于shell脚本中。它可以读取文本文件,对每一行进行处理,并输出结果。awk的基本语法为: awk 'pattern {action}' file 其中,pattern是一个正则表达式,用于匹配文本中的某些行;action是一个命令序列,用于对匹配到的行进行处理。awk会自动将每一行分割成若干个字段,可以通过$1、$2等变量来访问这些字段。例如,以下命令可以输出文件中第一列的内容: awk '{print $1}' file 除了基本语法外,awk还有很多高级用法,例如可以使用内置函数、变量、数组等。可以参考awk的官方文档或其他教程来学习更多内容。 ### 回答2: awk是一种文本处理工具,在shell脚本中经常用于对数据文件进行处理。它可以对文件进行逐行扫描,并按照指定的规则进行分割、匹配和处理。以下是awkshell脚本中的用法详解: 1. 基本语法 awk 'pattern { command }' filename 其中,pattern是匹配模式,用于匹配文件中的文本;command是要执行的命令,可以是一行或多行。filename是要处理的文件名。 2. 变量 在awk中有很多内置变量可以使用,例如: - $0:表示整行文本 - $1, $2, $3...:表示第一、二、三列文本 - NF:表示当前行的列数 - NR:表示当前行的行号 - FS:表示字段分隔符,默认为制表符或空格 可以使用这些变量来进行数据的处理和统计。 3. 示例 下面是一些常用的awk示例: (1)从文件中抽取出第一列 $ awk '{print $1}' file.txt (2)统计文件中每行的单词数 $ awk '{print NF}' file.txt (3)筛选出文件中包含关键词的行 $ awk '/keyword/' file.txt (4)计算文件中各列的和 $ awk '{sum += $1 + $2 + $3} END {print sum}' file.txt (5)替换文本中的字符串 $ awk '{gsub("oldstring", "newstring")}1' file.txt 4. 总结 awk是一种非常强大的文本处理工具,它能够根据指定的模式从文本中提取信息,并对其进行处理和统计。熟练掌握awk的使用可以让我们更轻松地处理和分析大量文本数据。 ### 回答3: Shell脚本是编程语言之一,它可以利用awk命令来处理和分析文本数据。awk命令是Linux/Unix系统中经常使用的一个工具,可以对文本文件或标准输入数据进行扫描、过滤、处理和分析,从而很好地完成文本处理的任务。 在Shell脚本中,使用awk命令需要按照如下结构: ```bash awk 'commands' filename ``` 其中,`commands`是awk命令的参数,可以是简单的字符串或复杂的处理脚本。`filename`是需要处理和分析的文件名或者通过管道传输的标准输入数据。 awk命令的一些常用参数和语法如下: 1. `awk '{pattern + action}' filename`:在文件中搜索指定的模式或文本,并对匹配模式的行执行指定的操作。 2. `awk '{print $n}' filename`:将文件中的某列数据提取出来进行打印输出,$1表示第一列数据,$2表示第二列数据,以此类推。 3. `awk -F: '{print $1,$3}' filename`:指定文件的分隔符为“:”,然后提取文件的第一列和第三列数据。 4. `awk '{sum+=$1} END {print sum}' filename`:计算文件中的数据列的总和值,并进行输出。 5. `awk '/re/ {print $0}' filename`:搜索指定的正则表达式re,并将匹配的行输出。 6. `awk '{if($1="xxx") print $0}' filename`:对文件中的指定数据列进行筛选,符合条件就进行输出。 以上是awk命令的一些常用参数和语法,值得注意的是,awk命令非常强大,可以完成很多复杂的文本处理和数据分析,几乎可以操作所有的文本数据。所以,对于Shell脚本中的awk用法,需要根据具体的需求和场景进行灵活运用和学习。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值