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

[经验分享] linux awk

[复制链接]

尚未签到

发表于 2019-2-17 12:15:24 | 显示全部楼层 |阅读模式
  awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。
  它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行中使用,但更多是作为脚本来使用。
  awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
  如果没有指定处理动作,则把匹配的行显示到标准输出 (屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。awk分别代表其作者姓氏的第一
  个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
  awk的两种形式语法格式
  awk [options] 'commands' filename
  awk [options] -f awk-script-file filename
  选项:
  -F 定义字段分隔符,默认的分隔符是连续的空格或制表符(tab)
  command:
  读前处理 行处理 读后处理
  BEGIN{}  {}     END{}
  awk命令格式:
  ===从文件输入:
  awk 'pattern' filename示例:awk -F: '/root/' /etc/passwd//打印出所有包含模式root的行
  awk '{action}' filename示例:awk -F: '{print $1}' /etc/passwd//打印每行的第一个域
  awk 'pattern {action}' filename示例:awk -F: '/root/{print $1,$3}' /etc/passwd//当匹配到模式root时,打印该行的1、3两个域
  ===从命令输入
  command |awk 'pattern'
  command |awk '{action}'示例:df -P |awk '$4 > 25000'
  command |awk 'pattern {action}'
  =====================================================================================================================================
  awk工作原理
  # awk -F: '{print $1,$3}' /etc/passwd
  (1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束
  (2)然后,行被空格分解成字段(或域),每个字段存储在已编号的变量中,从$1开始,最多达100个字段
  (3)awk如何知道空格是用来分隔字段的呢?因为有一个内部变量FS来确定字段的分隔符。初始时,FS被赋为空格
  (4)awk打印字段时,将以设置的方法使用print函数打印
  awk在打印的字段间加上空格,因为$1,$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格
  逗号被OFS变量中存储的字符替换
  (5)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
  ==========================================================================================================================================
  记录与字段
  $0:awk变量$0保存当前记录的内容# awk -F: '{print $0}' /etc/passwd
  NR:每条记录的记录号,每处理完一条记录,NR值加1# awk -F: '{print NR, $0}' /etc/passwd
  NF:保存记录的字段数,$1,$2...$100# awk -F: '{print $0,NF}' /etc/passwd
  FS:输入字段分隔符,默认空格# awk -F: '/alice/{print $1, $3}' /etc/passwd
  # awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd//使用多个字段分隔符
  OFS:输出字段分隔符# awk -F: '/alice/{print $1,$2,$3,$4}' /etc/passwd
  # awk -F: 'BEGIN{OFS="+++"} /^root/{print $1,$2,$3,$4}' /etc/passwd
  =========================================================================================================================================
  格式化输出:
  print函数
  # date |awk '{print "Month: "$2 "\nYear: ",$6}'
  # awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd
  # awk -F: '/root/{print "\t\tusername and uid: " $1,$3 "!"}' /etc/passwd
  printf函数
  # awk -F: '{printf "|%-15s|" "%-10s|" "%-15s|\n", $1,$2,$3}' /etc/passwd
  %s 字符类型
  %d 数值类型
  占15格的字符串
  - 表示左对齐,默认是右对齐
  printf默认不会在行尾自动换行,加\n
  =========================================================================================================================================
  模式和动作
  任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。
  如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。
  使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语句用来在awk完成
  文本浏览动作后打印输出文本总数和结尾状态标志。
  模式:awk模式用来控制awk对输入的文本执行什么操作。模式由正则表达式、判断条件表达式或二者的组合构成。
  # awk -F: '/alice/' /etc/passwd=# awk -F: '$0~/alice/' /etc/passwd
  # awk -F '$3 < 500' /etc/passwd
  动作:动作(action)是花括号中以分号分隔的语句
  # awk -F: '/^root/{print &quot;Hello, &quot; $1}' /etc/passwd
  正则表达式:
  # awk -F: '/alice/{print $1,$3}' /etc/passwd
  awk的正则表达式元字符
  元字符功能
  ^行首定位符
  $行尾定位符
  .匹配单个任意字符
  *匹配0或多个前导字符
  +匹配一个或多个前导字符
  ?匹配零个或一个前导字符
  []匹配一组字符中任意一个
  [a-z]匹配指定范围内的一个字符
  [^]匹配不在指定组内的字符
  (AB)+标签匹配字符
  A|B匹配A或B
  \*匹配星号本身
  &用在替代串中,代表查找串中匹配的内容
  \单词定位
  \(\)向前引用
  \{\}重复
  匹配整行:
  # awk '/^Mary/' employees
  # awk '/^[A-Z][a-z]+/' employees
  匹配操作符:匹配操作符(~)用于对记录或字段的表达式进行匹配
  # awk '$1~/[Bb]ill/' employees
  # awk '$1!~/ly$/' employees//显示所有第一个字段不是以ly结尾的行
  示例:
  # awk '/west/' datafile
  # awk '/^north/' datafile
  # awk '/^(no|so)/' datafile
  # awk '{print $3,$2}' datafile
  # awk '{print $3 $2}' datafile
  # awk '{print $0}' datafile
  # awk '{print &quot;Number of fields: &quot;NF}' datafile
  # awk '/northeast/{print $3,$2}' datafile
  # awk '/E/' datafile
  # awk '/^[ns]/{print $1}' datafile
  # awk '$5 ~ /\.[7-9]+/' datafile
  # awk '$2 !~ /E/{print $1,$2}' datafile
  # awk '$3 ~ /^Joel/{print $3 &quot; is a nice guy.&quot;}' datafile
  # awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile
  # awk '$4 ~ /Chin$/{print &quot;The price is $&quot; $8 &quot;.&quot;}' datafile
  # awk '/Tj/{print $0}' datafile
  # awk '{print $1}' datafile2//没有写datafile2
  # awk -F: '{print $1}' datafile2
  # awk '{print &quot;Number of fields: &quot;NF}' datafile2
  # awk -F: '{print &quot;Number of fields: &quot;NF}' datafile2
  # awk -F&quot;[ :]&quot; '{print $1,$2}' datafile2
  awk脚本:
  user1.awk
  BEGIN {
  FS=&quot;:&quot;
  }
  {
  if($3==0){
  print $1
  }
  else{
  print $7
  }
  }
  =================================================================
  user2.awk
  BEGIN{
  FS=&quot;:&quot;
  OFS=&quot;\t\t&quot;
  print &quot;username\tuid&quot;
  print &quot;-------------------&quot;
  }
  {if($3==0){
  print $1,$3;i++
  }
  }
  END{
  print &quot;-------------------&quot;
  print &quot;total users is: &quot;i
  }
  ======================================================================================================================================
  比较表达式:
  比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串
  关系运算符
  运算符含义示例
  y
  ~与正则表达式匹配x~/y/
  !~与正则表达式不匹配x!~/y/
  示例:
  # awk '$3 == 5346' employees
  # awk '$3 > 5000{print $1}' employees
  # awk '$2 ~ /Adam/' employees
  # awk '$2 !~ /Adm/' employee
  条件表达式:
  条件表达式的运算要用到两个符号:问号和冒号。条件表达式其实就是if/else语句的捷径,它们有着相同的结果
  {
  if (expression1)
  expression2
  else
  expression3
  }
  # awk -F: '{max=($3 > $4) ? $3: $4; print max}' /etc/passwd
  //如果第3个字段的值大于第4个字段的值,则把问号后那个表达式的值赋给max,否则就将冒号后那个表达式的值赋给max
  相当于:
  if ($3 > $4)
  max=$3
  else
  max=$4
  # awk -F: '{if($3>300) {print $0}}' /etc/passwd
  # awk -F: '{if($3>300){max=$3;print max} else{max=$1;print max}}' /etc/passwd
  # awk -F: '{max=($3>300)? $3: $1; print max}' /etc/passwd
  # awk -F: '{if($3>300){print $3} else{print $1}}' /etc/passwd
  算术运算:+ - * / %(模) ^(幂2^3)
  可以在模式中执行计算。awk都将按浮点方式执行算术运算
  # awk -F: '$3 * 10 > 500' /etc/passwd
  逻辑操作符和复合模式
  &&逻辑与a&&b
  ||逻辑或a||b
  !逻辑非!a
  # awk '$2 > 5 && $2  50' filename
  # awk '!($2 < 100 && $3 < 20)' filename//如果两个条件为真,awk将否定该表达式并取消对该行的打印
  范围模式
  # awk '/Tom/,/Suzanne/' filename
  复习
  # awk '$7 == 5' datafile
  # awk '$2 == &quot;CT&quot;{print $1, $2}' datafile
  # awk '$7 != 5' datafile
  # awk '$7 < 5 {print $4, $7}' datafile
  # awk '$6 > .9 {print $1,$6}' datafile
  # awk '$8 = 17 {print $8}' datafile
  # awk '$8 > 10 && $8 < 17' datafile
  # awk '$2 == &quot;NW&quot; || $1 ~ /south/{print $1, $2}' datafile
  # awk '!($8 == 13){print $8}' datafile
  # awk '/southem/{print $5 + 10}' datafile
  可以直接运算
  # awk '/southem/{print $8 + 10}' datafile
  # awk '/southem/{print $5 + 10.56}' datafile
  # awk '/southem/{print $8 - 10}' datafile
  # awk '/southem/{print $8 / 2 }' datafile
  # awk '/southem/{print $8 / 3 }' datafile
  # awk '/southem/{print $8 * 2 }' datafile
  # awk '/southem/{print $8 % 2 }' datafile
  # awk '$3 ~ /^Suan/{print &quot;Percentage: &quot;$6 + .2 &quot; Volume: &quot; $8}' datafile
  # awk '/^western/,/^eastern/' datafile
  # awk '{print ($7 > 4 ? &quot;high &quot;$7 : &quot;low &quot;$7)}' datafile//条件运算符
  # awk '$3 == &quot;Chris&quot;{$3 = &quot;Christian&quot;; print}' datafile//赋值运算符
  # awk '/Derek/{$8 += 12; print $8}' datafile//$8 += 12等价于$8 = $8 + 12
  # awk '{$7 %= 3; print $7}' datafile//$7 %= 3等价于$7 = $7 % 3
  流程控控制:
  if语句:
  格式
  {if(表达式){语句;语句;...}}
  awk -F: '{if($3==0)print $1 &quot; is administrator.&quot;}' /etc/passwd
  awk -F: '{if($3>0 && $30){count++;print $1}else{i++; print $3}}' /etc/passwd
  awk -F: '{if($3>0){count++} else{i++}} END{print &quot;管理员个 数: &quot;i &quot;\n系统用户数: &quot;count}' /etc/passwdd
  if/else和else if语句
  格式
  {if(表达式){语句;语句;...}else if(表达式){语句;语句;...}else if(表达式){语句;语句;...}else{语句;语句;...}}
  awk -F: '{if($3==0){i++} else if($3>499){k++} else{j++}} END{print i; print k; print j}' /etc/passwd
  [root@station40 awk]# awk -F: '{if($3==0){i++} else if($3>499){k++} else{j++}} END{print &quot;管理员个数: &quot;i; print &quot;普通用个数: &quot;k; print &quot;系统用户: &quot;j}' /etc/passwd
  管理员个数: 1
  普通用个数: 34
  系统用户: 36
  循环:
  while
  awk -F: '{i=1; while(i1000{print $3}' /etc/passwd                      //大于
  awk -F&quot;:&quot; '$3>=100{print $3}' /etc/passwd                     //大于等于
  awk -F&quot;:&quot; '$38) print }' /etc/passwd
  awk -F: '$1~/mail/ || $3>1000 {print }' /etc/passwd       //逻辑或
  awk -F: '{if($1~/mail/ || $3>1000) print }' /etc/passwd
  数值运算
  awk -F: '$3 > 100' /etc/passwd
  awk -F: '$3 > 100 || $3 < 5' /etc/passwd
  awk -F: '$3+$4 > 200' /etc/passwd
  awk -F: '/mysql|mail/{print $3+10}' /etc/passwd                    //第三个字段加10打印
  awk -F: '/mysql/{print $3-$4}' /etc/passwd                             //减法
  awk -F: '/mysql/{print $3*$4}' /etc/passwd                             //求乘积
  awk '/MemFree/{print $2/1024}' /proc/meminfo                  //除法
  awk '/MemFree/{print int($2/1024)}' /proc/meminfo           //取整
  输出分隔符OFS
  awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS=&quot;\t&quot; netstat.txt
  awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS=&quot;\t&quot; netstat.txt
  //输出字段6匹配WAIT的行,其中输出每行行号,字段4,5,6,并使用制表符分割字段
  输出处理结果到文件
  ①在命令代码块中直接输出    route -n|awk 'NR!=1{print > &quot;./fs&quot;}'
  ②使用重定向进行输出           route -n|awk 'NR!=1{print}'  > ./fs
  格式化输出
  netstat -anp|awk '{printf &quot;%-8s %-8s %-10s\n&quot;,$1,$2,$3}'
  printf表示格式输出
  %格式化输出分隔符
  -8长度为8个字符
  s表示字符串类型
  打印每行前三个字段,指定第一个字段输出字符串类型(长度为8),第二个字段输出字符串类型(长度为8),
  第三个字段输出字符串类型(长度为10)
  netstat -anp|awk '$6==&quot;LISTEN&quot; || NR==1 {printf &quot;%-10s %-10s %-10s \n&quot;,$1,$2,$3}'
  netstat -anp|awk '$6==&quot;LISTEN&quot; || NR==1 {printf &quot;%-3s %-10s %-10s %-10s \n&quot;,NR,$1,$2,$3}'
  IF语句
  awk -F: '{if($3>100) print &quot;large&quot;; else print &quot;small&quot;}' /etc/passwd
  small
  small
  small
  large
  small
  small
  awk -F: 'BEGIN{A=0;B=0} {if($3>100) {A++; print &quot;large&quot;} else {B++; print &quot;small&quot;}} END{print A,&quot;\t&quot;,B}' /etc/passwd
  //ID大于100,A加1,否则B加1
  awk -F: '{if($3

运维网声明 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.yunweiku.com/thread-673561-1-1.html 上篇帖子: linux sed 下篇帖子: linux shell基本特性
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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