zoukankan      html  css  js  c++  java
  • awk编程基础

    一、awk介绍
    awk(名字来源于三个创始人姓氏首字母)是linux系统下文本编辑工具,是一门编程语言,有自己的基本语法和流程控制、函数。awk简单高效。
     
    二、awk的运行方法
    例子:使用冒号:分割/etc/passwd,打印出第一列
    1.通过命令行执行
    awk -F: '{print $1}' /etc/passwd
     
    2.通过执行awk文件来执行
    awk文件的格式:
    #!/usr/bin/awk
    BEGIN{ FS=":"}
    {print $1}
     
    然后调用这个awk文件的格式:awk -f awk脚本文件 /etc/passwd
     
    三、awk的基本语法
    awk通过FS作为每一段文本的分割符(默认空格),在命令行上可以用-F参数指定分隔符;
    通过RS参数指定文本换行符(默认回车,所以是一行行取数据的),通过换行符作为分割来读取文件。这里区别于sed,sed是一行一行读取文件的
    基本流程:
         BEGIN{在读取文件之前做的操作}
         {读取文件时做的操作}
         END{全部文件读取之后才进行的操作}
     
    常用内置变量:
         $0  当前所有字段
         $1--$n 按照分隔符分割取到的第n列内容
         FS  分隔符(默认空格) awk 'BEGIN{FS=":"}{print $1}' /etc/passwd ;等价于awk -F: '{print $1}' /etc/passwd
         RS  换行符(默认回车) awk 'BEGIN{RS=":"}{print $1}' /etc/passwd
         NF  字符列数,当前处理行的分割后的列数 awk -F: '{print NF}' /etc/passwd
         NR  行号 awk -F: '{print NR ":" $1}' /etc/passwd
         OFS (默认空格)输出字段分隔符
         ORS (默认回车)输出记录分隔符
     
    自定义外部变量:
         -v:自定义变量
         awk -v host=$HOSTNAME "BEGIN{print host}"
     
    关系操作符:<、>、<=、>=、==、!=、~、!~
         比较符<等与其他的语言类似,重点说一下不一样的
         ~:用来判断前面的列是否匹配后面的内容。例如awk -F: '$7 ~ /^/bin/{print $0}' /etc/passwd(判断第7列是否以/bin开头,如果是打印该列)
         !~:不匹配
     
    输出:print与printf
         print:直接输出 awk -F: '{print $1 ":" $2}' /etc/passwd
         printf:格式化输出(printf是一个函数,需要用到())
              awk -F: '{printf(hello %s:%s ),$1,$2}'
              注意:printf需要手动增加 来换行。使用%s来格式化,printf()外加入要替换的变量
     
    四、awk的流程控制
    条件:
    if语句 if(expression){action1}else{action2}
         例如:产生10个数seq 10,通过if语句判断是单数还是双数
         seq 10 |awk '{if($0%2==0){print $0"是双数"}else{print $0"是单数"}}'
     
    如果只需要一个if分支,可以省略前面的if,比如awk -F: '$3<-10 {print $1}' /etc/passwd
     
    循环:
    while语句:while(expression){action}
         例子:使用:分割/etc/passwd,并将每一列前加上列号
         awk -F: '{i=1;while(i<=NF){print i":"$i;i++ }}' /etc/passwd
     
    for语句:
    第一种方法:for(i=0;i<=10;i++){action}
         例子:使用:分割/etc/passwd,并将每一列前加上列号
         awk -F: '{for(i=1;i<=NF;i++){print i":"$i}}' /etc/passwd
     
    第二种方法:for(value in array){action}
    当value在array的key中,进行下面的操作。awk的数组类似python中的字典。
         例子:统计/etc/passwd第7列的值及对应的个数
         awk -F: '{a[$7]++}END{for(i in a)if(i!=""){print i":"a[i]}}' /etc/passwd
         说明:a[$7]:将$7作为数组a的key,然后统计对应的个数;然后遍历for(i in a),判断i是否在数组a的key中;如果存在则打印a[i],a[i]为对应key的值,这里指个数。
     
    数组:
    array[1]="hello"
    array["name"]="Jack"
    数组类似python的字典,array[key值]="value值";key为索引,可以是数字也可以是字符串。
    数组元素的删除:delete array["key"]
     
         例子:定义了数组a的三个值,并打印结果查看
         awk 'BEGIN{a[1]="hello";a[2]="word";a["name"]="meitian";for(i in a){print "key为"i":value为"a[i]}}'
      
    五、awk函数
    内置函数
    1.算术函数:
    int(x) 返回x的整数部分的值,值不会四舍五入,只是取整
    sqrt(x) 返回x的平方根
    rand() 返回伪随机数r,其中0<=r<1,(伪随机数指返回的值都是上一次返回的同一个随机数)
    srand(x) 建立rand()新的种子数,如果没有指定就用当天的时间(使用srand()可以使得rand()返回不同的随机数)
         例子:rand()产生一个随机数,通过srand()产生新的种子数,然后再差生一个随机数
         awk 'BEGIN{print rand();srand();print rand()}'
    2.字符串函数:
    sub("要替换的字符串","替换后的字符串值"):替换匹配到的第一个文本
         echo "hello world world" | awk '{sub("world","meitian");print $0}'
    gsub("要替换的字符串","替换后的字符串值" ):开启全局替换,替换文本中所有匹配到的字符串
         echo "hello world world" | awk '{gsub("world","meitian");print $0}'
         
    index("a","b"):返回字符串b在字符串a中开始的位置
         awk 'BEGIN{print index("hello world","world")}'
    length("s"):返回字符串s的长度,当没有指定s时,返回$0的长度
          awk -F 'BEGIN{print length("hello world")}{print lenght()}' /etc/passwd
    match("s","r"):如果正则表达式r在s中匹配到,则返回出现的起始位置,否则返回0
         awk 'BEGIN{print match("hello world","[wo]")}'
    split(s,a,sep) 使用sep将字符串s分解到数组a中,默认sep为FS。
         例子:使用o做为分隔符,将"hello world"进行分割存储到数组a中
         awk 'BEGIN{print split("hello world",a,"o");for(i in a){print a[i]}}'
      
    toupper(s):将所有小写字母转换成大写字母
         echo "hello world" |awk '{print toupper($0)}'
    tolower(s):将所有大写字母转换成小写字母
         echo "HELLO WORLD" |awk '{print tolower($0)}'
     
    自定义函数:
    function 函数名(参数1,参数2,...){语句;return 表达式}
         例子:求和
         awk 'function sum(a,b){total=a+b;return total}BEGIN{print sum(2,3)}'
    注意:函数必须写在BEGIN{}{}END{}的花括号之外的地方,不能放在任何{}内,否则会报错`return' used outside function context
     
    六、实战
    1.获得eth0的IP地址
    ifconfig eth0 | awk -F":| +" '/inet addr:/{print $4}'
    ifconfig eth0的结果:
    说明:
    1.多个字符作为分隔符(比如例子中的冒号和空格),可以使用|来区分;或者直接使用正则来作区分。比如例子中的-F":| +"可以写成-F"[ :]+"
    2.如果要过滤多个相同分隔符,可以使用正则的+。表示1个或多个
    3.awk中可以使用'/操作匹配到该内容的行/{匹配到前面的行后进行的操作}'来选择某些想要的行。比如例子中需要取匹配到“inet addr:”的行,打印第4列,//中的为正则表达式,如果有/等需要使用进行转义
     
    2.统计tcp网络连接数
    netstat -an |awk  '/^tcp/{a[$NF]++}END{for(i in a){printf("%s:%d ",i,a[i])}}'
    说明:与上面的例子大同小异,/^tcp/表示只处理以tcp开头的行。$NF表示最后一列 
     
    七、在实战中可能用到的注意点
    1.awk需要对文件进行处理。不需要处理文件的可以把打印命令写在BEGIN里(例如:awk -v name=meitian 'BEGIN{print name}')
    2.可以对ls等命令结果进行处理
         例子:对包含conf的文件按照.进行分割,并将分割结果用冒号进行连接
         ls |grep conf |awk -F. '{print $1 ":" $2}'
    3.awk使用-v定义变量,但是awk中引用变量时直接使用变量名,不需要在变量前加$
    4.将awk中的结果赋值给变量传递给shell中用
    方法一:可以使用eval()函数来将打印的结果转换成变量。eval会将打印的值当做命令来进行处理,shell中定义变量的格式:变量名=变量值
         例子:有个文件名为search.contract-0.0.5-SNAPSHOT.jar,按照-分割。将-前面的存为name变量,中间的版本号存为version变量。
         eval $(ls |grep search.contract-0.0.5-SNAPSHOT.jar |awk -F"-" '{printf("name=%s;version=%s ",$1,$2)}')
     
      
     
    方法二:如果只想保存一个变量,可以通过变量名=$(操作print变量值)的方法来保存  
         例如提取ifconfig eth0本机中的IP地址保存到变量a中
         a=$(ifconfig eth0 |awk -F":| *" '/inet addr/{print $4}')
      
    5.只对包含某些内容的行进行操作
         awk '/要匹配的内容/{进行的操作}' file,//内可以放入正则表达式,注意对一些特殊字符进行转义,比如“[]“
    6.awk不能直接修改源文件,可以通过重导向输出结果来修改原文件。>(全部覆盖文件内容)或>>(追加到文件)
         awk '/^root/{print $0 >"passwd"}' passwd
         注意:重导向输出的文件名要用双引号括起来,否则会报错 
    7.awk使用双引号作为分隔符,可以使用单引号括起来,'"'
  • 相关阅读:
    ini_set /ini_get函数功能-----PHP
    【转】那个什么都懂的家伙
    word 2007为不同页插入不同页眉页脚
    August 26th 2017 Week 34th Saturday
    【2017-11-08】Linux与openCV:opencv版本查看及库文件位置等
    August 25th 2017 Week 34th Friday
    August 24th 2017 Week 34th Thursday
    August 23rd 2017 Week 34th Wednesday
    August 22nd 2017 Week 34th Tuesday
    August 21st 2017 Week 34th Monday
  • 原文地址:https://www.cnblogs.com/Jace06/p/8854578.html
Copyright © 2011-2022 走看看