设为首页 收藏本站
查看: 965|回复: 0

Shell文本处理三剑客(二)

[复制链接]
发表于 2018-8-27 07:06:30 | 显示全部楼层 |阅读模式
  防伪码:锄禾日当午,汗滴禾下土。
  8.3 awk
  awk 是一个处理文本的编程语言工具,能用简短的程序处理标准输入或文件、数据排序、计算以及
  生成报表等等。
  在 Linux 系统下默认 awk 是 gawk,它是 awk 的 GNU 版本。可以通过命令查看应用的版本:ls -l
  /bin/awk
  基本的命令语法:awk option 'pattern {action}' file
  其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。
  花括号用于根据特定的模式对一系列指令进行分组。
  awk 处理的工作方式与数据库类似,支持对记录和字段处理,这也是 grep 和 sed 不能实现的。
  在 awk 中,缺省的情况下将文本文件中的一行视为一个记录,逐行放到内存中处理,而将一行中的
  某一部分作为记录中的一个字段。用 1,2,3...数字的方式顺序的表示行(记录)中的不同字段。用
  $后跟数字,引用对应的字段,以逗号分隔,0 表示整个行。
  8.3.1  选项
  选项  描述
  -f program-file  从文件中读取 awk 程序源文件
  -F fs  指定 fs 为输入字段分隔符
  -v var=value  变量赋值
  --posix  兼容 POSIX 正则表达式
  --dump-variables=[file]  把 awk 命令时的全局变量写入文件,
  默认文件是 awkvars.out
  --profile=[file]  格式化 awk 语句到文件,默认是 awkprof.out
  8.3.2  模式
  常用模式有:
  Pattern  Description
  BEGIN{ }  给程序赋予初始状态,先执行的工作
  END{ }  程序结束之后执行的一些扫尾工作
  /regular expression/  为每个输入记录匹配正则表达式
  pattern && pattern  逻辑 and,满足两个模式
  pattern || pattern  逻辑 or,满足其中一个模式
  ! pattern  逻辑 not,不满足模式
  pattern1, pattern2  范围模式,匹配所有模式 1 的记录,直到匹配到模式 2
  而动作呢,就是下面所讲的 print、流程控制、I/O 语句等。
  示例:
  1)从文件读取 awk 程序处理文件
  # vi test.awk
  {print $2}
  # tail -n3 /etc/services |awk -f test.awk
  48049/tcp
  48128/tcp
  49000/tcp
  2)指定分隔符,打印指定字段
  打印第二字段,默认以空格分隔:
  # tail -n3 /etc/services |awk '{print $2}'
  48049/tcp
  48128/tcp
  48128/udp
  指定冒号为分隔符打印第一字段:
  # awk -F ':' '{print $1}' /etc/passwd
  root
  bin
  daemon
  adm
  lp
  sync
  ......
  还可以指定多个分隔符,作为同一个分隔符处理:
  # tail -n3 /etc/services |awk -F'[/#]' '{print $3}'
  iqobject
  iqobject
  Matahari Broker
  # tail -n3 /etc/services |awk -F'[/#]' '{print $1}'
  iqobject 48619
  iqobject 48619
  matahari 49000
  # tail -n3 /etc/services |awk -F'[/#]' '{print $2}'
  tcp
  udp
  tcp
  # tail -n3 /etc/services |awk -F'[/#]' '{print $3}'
  iqobject
  iqobject
  Matahari Broker
  # tail -n3 /etc/services |awk -F'[ /]+' '{print $2}'
  48619
  48619
  49000
  []元字符的意思是符号其中任意一个字符,也就是说每遇到一个/或#时就分隔一个字段,当用多个
  分隔符时,就能更方面处理字段了。
  3)变量赋值
  # awk -v a=123 'BEGIN{print a}'
  123
  系统变量作为 awk 变量的值:
  # a=123
  # awk -v a=$a 'BEGIN{print a}'
  123
  或使用单引号
  # awk 'BEGIN{print '$a'}'
  123
  4)输出 awk 全局变量到文件
  # seq 5 |awk --dump-variables '{print $0}'
  1
  2
  3
  4
  5
  # cat awkvars.out
  ARGC: number (1)
  ARGIND: number (0)
  ARGV: array, 1 elements
  BINMODE: number (0)
  CONVFMT: string ("%.6g")
  ERRNO: number (0)
  FIELDWIDTHS: string ("")
  FILENAME: string ("-")
  FNR: number (5)
  FS: string (" ")
  IGNORECASE: number (0)
  LINT: number (0)
  NF: number (1)
  NR: number (5)
  OFMT: string ("%.6g")
  OFS: string (" ")
  ORS: string ("\n")
  RLENGTH: number (0)
  RS: string ("\n")
  RSTART: number (0)
  RT: string ("\n")
  SUBSEP: string ("\034")
  TEXTDOMAIN: string ("messages")
  5)BEGIN 和 END
  BEGIN 模式是在处理文件之前执行该操作,常用于修改内置变量、变量赋值和打印输出的页眉或标
  题。
  例如:打印页眉
  # tail /etc/services |awk 'BEGIN{print "Service\t\tPort\t\t\tDescription\n==="}{print
  $0}'
  Service Port Description
  ===
  3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service
  isnetserv 48128/tcp # Image Systems Network Services
  isnetserv 48128/udp # Image Systems Network Services
  blp5 48129/tcp # Bloomberg locator
  blp5 48129/udp # Bloomberg locator
  com-bardac-dw 48556/tcp # com-bardac-dw
  com-bardac-dw 48556/udp # com-bardac-dw
  iqobject 48619/tcp # iqobject
  iqobject 48619/udp # iqobject
  matahari 49000/tcp # Matahari Broker
  END 模式是在程序处理完才会执行。
  例如:打印页尾
  # tail /etc/services |awk '{print $0}END{print "===\nEND......"}'
  3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service
  isnetserv 48128/tcp # Image Systems Network Services
  isnetserv 48128/udp # Image Systems Network Services
  blp5 48129/tcp # Bloomberg locator
  blp5 48129/udp # Bloomberg locator
  com-bardac-dw 48556/tcp # com-bardac-dw
  com-bardac-dw 48556/udp # com-bardac-dw
  iqobject 48619/tcp # iqobject
  iqobject 48619/udp # iqobject
  matahari 49000/tcp # Matahari Broker
  ===
  END......
  6)格式化输出 awk 命令到文件
  # tail /etc/services |awk --profile 'BEGIN{print
  "Service\t\tPort\t\t\tDescription\n==="}{print $0}END{print "===\nEND......"}'
  Service Port Description
  ===
  nimgtw 48003/udp # Nimbus Gateway
  3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service Protocol
  isnetserv 48128/tcp # Image Systems Network Services
  isnetserv 48128/udp # Image Systems Network Services
  blp5 48129/tcp # Bloomberg locator
  blp5 48129/udp # Bloomberg locator
  com-bardac-dw 48556/tcp # com-bardac-dw
  com-bardac-dw 48556/udp # com-bardac-dw
  iqobject 48619/tcp # iqobject
  iqobject 48619/udp # iqobject
  ===
  END......
  # cat awkprof.out
  # gawk profile, created Sat Jan 7 19:45:22 2017
  # BEGIN block(s)
  BEGIN {
  print "Service\t\tPort\t\t\tDescription\n==="
  }
  # Rule(s)
  {
  print $0
  }
  # END block(s)
  END {
  print "===\nEND......"
  }
  7)/re/正则匹配
  匹配包含 tcp 的行:
  # tail /etc/services |awk '/tcp/{print $0}'
  3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service
  isnetserv 48128/tcp # Image Systems Network Services
  blp5 48129/tcp # Bloomberg locator
  com-bardac-dw 48556/tcp # com-bardac-dw
  iqobject 48619/tcp # iqobject
  matahari 49000/tcp # Matahari Broker
  匹配开头是 blp5 的行:
  # tail /etc/services |awk '/^blp5/{print $0}'
  blp5 48129/tcp # Bloomberg locator
  blp5 48129/udp # Bloomberg locator
  匹配第一个字段是 8 个字符的行:
  # tail /etc/services |awk '/^[a-z0-9]{8} /{print $0}'
  iqobject 48619/tcp # iqobject
  iqobject 48619/udp # iqobject
  matahari 49000/tcp # Matahari Broker
  如果没有匹配到,请查看你的 awk 版本(awk --version)是不是 3,因为 4 才支持{}
  8)逻辑 and、or 和 not
  匹配记录中包含 blp5 和 tcp 的行:
  # tail /etc/services |awk '/blp5/ && /tcp/{print $0}'
  blp5 48129/tcp # Bloomberg locator
  匹配记录中包含 blp5 或 tcp 的行:
  # tail /etc/services |awk '/blp5/ || /tcp/{print $0}'
  3gpp-cbsp 48049/tcp # 3GPP Cell Broadcast Service
  isnetserv 48128/tcp # Image Systems Network Services
  blp5 48129/tcp # Bloomberg locator
  blp5 48129/udp # Bloomberg locator
  com-bardac-dw 48556/tcp # com-bardac-dw
  iqobject 48619/tcp # iqobject
  matahari 49000/tcp # Matahari Broker
  不匹配开头是#和空行:
  # awk '! /^#/ && ! /^$/{print $0}' /etc/httpd/conf/httpd.conf
  或
  # awk '! /^#|^$/' /etc/httpd/conf/httpd.conf
  或
  # awk '/^[^#]|"^$"/' /etc/httpd/conf/httpd.conf
  9)匹配范围
  # tail /etc/services |awk '/^blp5/,/^com/'
  blp5 48129/tcp # Bloomberg locator
  blp5 48129/udp # Bloomberg locator
  com-bardac-dw 48556/tcp # com-bardac-dw
  对匹配范围后记录再次处理,例如匹配关键字下一行到最后一行:
  # seq 5 |awk '/3/,/^$/{printf /3/?"":$0"\n"}'
  4
  5
  另一种判断真假的方式实现:
  # seq 5 |awk '/3/{t=1;next}t'
  4
  5
  1 和 2 都不匹配 3,不执行后面{},执行 t,t 变量还没赋值,为空,空在 awk 中就为假,就不打印
  当前行。匹配到 3,执行 t=1,next 跳出,不执行 t。4 也不匹配 3,执行 t,t 的值上次赋值的 1,
  为真,打印当前行,以此类推。(非 0 的数字都为真,所以 t 可以写任意非 0 数字)
  如果想打印匹配行都最后一行,就可以这样了:
  # seq 5 |awk '/3/{t=1}t'
  3
  4
  5
  8.3.3  内置变量
  变量名  描述
  FS  输入字段分隔符,默认是空格或制表符
  OFS  输出字段分隔符,默认是空格
  RS  输入记录分隔符,默认是换行符\n
  ORS  输出记录分隔符,默认是换行符\n
  NF  统计当前记录中字段个数
  NR  统计记录编号,每处理一行记录,编号就会+1
  FNR  统计记录编号,每处理一行记录,编号也会+1,与 NR 不同的是,处理第二个
  文件时,编号会重新计数。
  ARGC  命令行参数数量
  ARGV  命令行参数数组序列数组,下标从 0 开始,ARGV[0]是 awk
  ARGIND  当前正在处理的文件索引值。第一个文件是 1,第二个文件是 2,以此类推
  ENVIRON  当前系统的环境变量
  FILENAME  输出当前处理的文件名
  IGNORECASE  忽略大小写
  SUBSEP  数组中下标的分隔符,默认为"\034"
  示例:
  1)FS 和 OFS
  在程序开始前重新赋值 FS 变量,改变默认分隔符为冒号,与-F 一样。
  # awk 'BEGIN{FS=":"}{print $1,$2}' /etc/passwd |head -n5
  root x
  bin x
  daemon x
  adm x
  lp x
  也可以使用-v 来重新赋值这个变量:
  # awk -vFS=':' '{print $1,$2}' /etc/passwd |head -n5 # 中间逗号被换成了 OFS 的默
  认值
  root x
  bin x
  daemon x
  adm x
  lp x
  由于 OFS 默认以空格分隔,反向引用多个字段分隔的也是空格,如果想指定输出分隔符这样:
  # awk 'BEGIN{FS=":";OFS=":"}{print $1,$2}' /etc/passwd |head -n5
  root:x
  bin:x
  daemon:x
  adm:x
  lp:x
  也可以通过字符串拼接实现分隔:
  # awk 'BEGIN{FS=":"}{print $1"#"$2}' /etc/passwd |head -n5
  root#x
  bin#x
  daemon#x
  adm#x
  lp#x
  2)RS 和 ORS
  RS 默认是\n 分隔每行,如果想指定以某个字符作为分隔符来处理记录:
  # echo "www.baidu.com/user/test.html" |awk 'BEGIN{RS="/"}{print $0}'
  www.baidu.com
  user
  test.html
  RS 也支持正则,简单演示下:
  # seq -f "str%02g" 10 |sed 'n;n;a\-----' |awk 'BEGIN{RS="-+"}{print $1}'
  str01
  str04
  str07
  str10
  将输出的换行符替换为+号:
  # seq 10 |awk 'BEGIN{ORS="+"}{print $0}'
  1+2+3+4+5+6+7+8+9+10+
  替换某个字符:
  # tail -n2 /etc/services |awk 'BEGIN{RS="/";ORS="#"}{print $0}'
  iqobject 48619#udp # iqobject
  matahari 49000#tcp # Matahari Broker
  3)NF
  NF 是字段个数。
  # echo "a b c d e f" |awk '{print NF}'
  6
  打印最后一个字段:
  # echo "a b c d e f" |awk '{print $NF}'
  f
  打印倒数第二个字段:
  # echo "a b c d e f" |awk '{print $(NF-1)}'
  e
  排除最后两个字段:
  # echo "a b c d e f" |awk '{$NF="";$(NF-1)="";print $0}'
  a b c d
  排除第一个字段:
  # echo "a b c d e f" |awk '{$1="";print $0}'
  b c d e f
  4)NR 和 FNR
  NR 统计记录编号,每处理一行记录,编号就会+1,FNR 不同的是在统计第二个文件时会重新计数。
  打印行数:
  # tail -n5 /etc/services |awk '{print NR,$0}'
  1 com-bardac-dw 48556/tcp # com-bardac-dw
  2 com-bardac-dw 48556/udp # com-bardac-dw
  3 iqobject 48619/tcp # iqobject
  4 iqobject 48619/udp # iqobject
  5 matahari 49000/tcp # Matahari Broker
  打印总行数:
  # tail -n5 /etc/services |awk 'END{print NR}'
  5
  打印第三行:
  # tail -n5 /etc/services |awk 'NR==3'
  iqobject 48619/tcp # iqobject
  打印第三行第二个字段:
  # tail -n5 /etc/services |awk 'NR==3{print $2}'
  48619/tcp
  打印前三行:
  # tail -n5 /etc/services |awk 'NR=1;i--)if(i==1)printf $i"\n";else printf $i" "}' file
  3 2 1
  6 5 4
  6 5 4
  9 8 7
  在这种情况下,是不是就排除第一行和倒数第一行呢?我们正序打印看下
  排除第一行:
  # awk '{for(i=2;i

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-556962-1-1.html 上篇帖子: Shell文本处理三剑客(一) 下篇帖子: linux shell下除了某个文件外的其他文件全部删除的命令
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表