linux学习:awk和RE

awk

awk是一种用于处理文本的编程语言工具,他扫描文件中的每一行,查找与命令行中所给定内容相匹配的模式,如果发现匹配内容,则进行下一个编程步骤。如果找 不到匹配内容,则继续处理下一行

awk ‘条件 1 {动作 1} 条件 2 {动作 2} ……’ file

从 file 中每次读取一行,然后针对这一行判断条件 1,成立则执行动作 1, 否则不执行,然后判断条件 2,成立则执行动作 2,否则不执行,以此类推。如果一个动作 前面没有条件,则这个动作就可以“无条件”执行

内建变量

  • $0 当前记录(这个变量中存放着整个行的内容)
  • $1~$n 当前记录的第 n 个字段,字段间由
  • FS 分隔 FS 输入字段分隔符 默认是空格或 Tab
  • NF 当前记录中的字段个数,就是有多少列
  • NR 行号,从1开始,如果有多个文件这个值将不断累加。
  • FNR 当前记录数,与 NR 不同的是,这个值会是各个文件自己的行号
  • RS 输入的记录分隔符, 默认为换行符
  • OFS 输出字段分隔符, 默认也是空格
  • ORS 输出的记录分隔符,默认为换行符
  • FILENAME 当前输入文件的名字

例子1   读取文件

 awk ‘NR==1 { print $0 } NF==5 { print $1 }’ file

awk 从 file 中读取数据,每次读取一行,读到一行数据之后 判断每一个条件是否成立,如果成立则执行花括号里面的动作,比如 NR==1 成立则执行 print $0,然后再判断 NF==5 是否成立来决定是否执行 print $1。然后读取下一行,以 此类推

例子2   输出txt

有下面一个txt文件

  1. 打印指定列(例如名字和年龄)
     awk ‘{ print $1, $5 }’ grade.txt

    从 grade.txt 中读取一行,然后执行条件语句(该 示例中没有条件语句),然后执行动作(即 print $1, $5)。完了继续读取下一行,就这 样循环递进

  2. 格式化输出(和 C 语言一样)
    awk ‘{printf "%-10s:%-d\n", $1, $5}’ grade.txt
  3. 过滤
     awk ‘$5==11 && $6>=90 { print $0 }’ grade.txt

    :读取 grade.txt 的一行信息,判断第五列(即$5)是否等于 11 而且第 6 列(即$6) 是否大于等于 90,如果是,则打印整一行(即 print $0)。然后读取下一行。

  4. 打印表头,引入内建变量 NR
     awk ‘NR==1 || $6>=90 { print }’ grade.txt

    注意:1,NR 是一个所谓的内建变量,表示已经读出的记录数(即行号) 2,print 后面什么都没跟,等价于 print $0

例子3   指定分隔符

 awk ‘BEGIN { FS=”:” } { print $1 }' /etc/passwd
等价于
 awk -F: ‘{ print $1 }’ /etc/passwd

BEGIN 意味着紧跟在它后面的动作{FS=”:”}会在 awk

  1. 如果有多个分隔符
     awk -F‘[\t;:]’ ‘{ print $1 }’ /etc/passwd

    其中-F’[\t;:]’的意思是:指定制表符、分号以及冒号为分隔符。

例子4  使用正则表达式匹配字符串

 awk ‘$0~/Brown/ {print}’ grade.txt

将所有匹配 Brown 的行打印出来。其中,$0~/Brown/是一个条件,表示所指定 的域(这里是$0)要匹配的规则(这里是 Brown),也就是说,grade.txt 中的一行只要 包含有单词 Brown,就会被选出来然后打印出来。

这里的单词 Brown 被包含在两个正斜杠之间,事实上这两个正斜杠之间写 的就是大名鼎鼎的“正则表达式”,就是RE 

grep ‘[^ ]*ing ’ example.txt  查询txt中ing结尾的字符在哪一行并输出

特殊符号

例子5  使用模式取反的例子

 awk '$0!~/Brown.*/ {print}' grade.txt

将所有不匹配 Brown 的行打印出来

例子6  拆分文件

将各年龄段的孩子的信息分别存放在各个文件中

 awk '{print > $5}' grade.txt

每一行都将被重定向到以第 5 个域(年龄)命名的文件中去

也可以将指定的域重定位到相应的文件

 awk '{print $1, $6 > $5}' grade.txt

将每一行中的姓名和分数重定位到与其年龄相应的文件中去

例子7  按级别将信息分成三个文件

 awk '{ if($4~/Brown.*|Black/) print > "high.txt";
> else if($4~/Yellow|[Gg]reen/) print > "midle.txt";
> else print > "low.txt" }' grade.txt

如果记录中的第 4 个域($4)匹配 Brown.*或者 Black,就将该记录重定位 到文件 high.txt 中,如果匹配 Yellow 或者[Gg]reen,就重定位到 midle.txt 中,否则统 统重定位到 low.txt 中

例子8  统计

将所有孩子的分数累积起来并打印出来

 awk '{sum+=$6} END{print sum}' grade.txt

END 表示紧跟其后的语句只会在 awk 处理完所有行之后才被执行

例子9  统计各个级别的人数

 awk 'NR!=1 {a[$4]++;}
> END{for(i in a) print i","a[i];}' grade.txt

$4 是级别名称,例如 Yellow、Brown 等,a 是一个以这些级别为下标的数组, 其值从零开始计算

awk脚本

想象我现在要打印出整个班级的所有孩子的信息,而且在最前面把表头也打印出来, 而且下面要打印一行“===========”来跟具体内容加以划分。并且在最后一行,统 计孩子们的平均年龄以及平均分数。将 awk语句组织成脚本,如下:

1 #!/usr/bin/awk -f #-f 表示运行该脚本需要指定一个文件作为输入
2
3 BEGIN{ #awk 开始运行之前的准备工作
4     age = 0
5     score = 
6 }
7 {
8     if(NR==1) #打印表头已经分割线
9     {
10         print $0
11         printf "=============" #由于是 printf,没有\n 就不换行
12         print "=============" #由于是 print,会自动换行
13     }
14     else
15     {
16         age+=$5
17         score+=$6
18         print $0
19     }
20 }
21 END{ #awk 处理完所有的记录之后,END 才开始运行
22     printf "======================" 
23     print "======================" 
24     print "Average:\t\t\t\t\t"age/NR ",\t" score/NR
25 }

  • 15
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

码农小白

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

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

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

打赏作者

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

抵扣说明:

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

余额充值