• awk内置函数


    算数函数

    最常用的算数函数有rand函数、srand函数、int函数。

    可以使用rand函数生成随机数,但是使用rand函数时,需要配合srand函数,否则rand函数返回的值将一直不变,示例如下。

    [root@server01 ~]# awk 'BEGIN{print rand()}'
    0.237788
    [root@server01 ~]# awk 'BEGIN{print rand()}'
    0.237788
    [root@server01 ~]# awk 'BEGIN{print rand()}'
    0.237788

    可以看到,如果单纯的使用rand函数,生成的值是不变的,可以配合srand函数,生成一个大于0小于1的随机数,示例如下

    [root@server01 ~]# awk 'BEGIN{srand();print rand()}'
    0.881739
    [root@server01 ~]# awk 'BEGIN{srand();print rand()}'
    0.419895
    [root@server01 ~]# awk 'BEGIN{srand();print rand()}'
    0.352016

    可以看到,上例中生成的随机数都是小于1的小数,如果我们想要生成整数随机数,可以将上述生成的随机数乘以100,然后截取整数部分,使用int函数可以截取整数部分的值,示例如下

    [root@server01 ~]# awk 'BEGIN{srand();print rand()}'
    0.222916
    [root@server01 ~]# awk 'BEGIN{srand();print 100*rand()}'
    66.5736
    [root@server01 ~]# awk 'BEGIN{srand();print int(100*rand())}'
    58
    [root@server01 ~]# awk 'BEGIN{srand();print int(100*rand())}'
    59
    [root@server01 ~]# awk 'BEGIN{srand();print int(100*rand())}'
    10
    [root@server01 ~]# awk 'BEGIN{srand();print int(100*rand())}'
    48
    [root@server01 ~]# 

    经过上述处理以后,可以得到一个小于100的随机整数。

    字符串函数

    我们可以使用gsub函数或sub函数替换某些文本,先来 看看gsub函数怎样使用。

    如果我们想要将如下文本中的第一列中的小写字母"l"都替换成大写字母"L",则可以使用gsub函数,示例如下。

    [root@server01 ~]# cat test11
    Allen Phillips
    Green Lee
    William Ken Allen
    [root@server01 ~]# awk '{gsub("l","L",$1);print $0}' test11
    ALLen Phillips
    Green Lee
    WiLLiam Ken Allen

    如上图所示,我们使用gsub函数,将小写字母"l"替换成大写字母"L",但是替换的范围只限于"$1",所以,当我们再次输出文本时,发现只有文本中的第一列中的小写字母"l"被替换成了大写字母"L",其他列中的小写字母"l"并未被替换,当然,如果你想要替换文本中所有的小写字母"l",则可以将上图中的"$1"换成"$0",或者省略gsub函数中的第三个参数,省略gsub中的第三个参数时,默认为"$0",示例如下。

    [root@server01 ~]# awk '{gsub("l","L");print $0}' test11
    ALLen PhiLLips
    Green Lee
    WiLLiam Ken ALLen
    [root@server01 ~]# awk '{gsub("l","L",$0);print $0}' test11
    ALLen PhiLLips
    Green Lee
    WiLLiam Ken ALLen

    看完上述示例,我想你应该已经明白了gsub函数的作用,没错,gsub函数会在指定范围内查找指定的字符,并将其替换为指定的字符串。

    其实,我们还可以根据正则表达式,替换字符串,示例如下。

    [root@server01 ~]# awk '{gsub("[a-z]","6",$1);print $0}' test11
    A6666 Phillips
    G6666 Lee
    W666666 Ken Allen

    那么sub函数与gsub函数有什么不同呢?我们来对比一下。

    [root@server01 ~]# awk '{gsub("l","L",$1);print $0}' test11
    ALLen Phillips
    Green Lee
    WiLLiam Ken Allen
    [root@server01 ~]# awk '{sub("l","L",$1);print $0}' test11
    ALlen Phillips
    Green Lee
    WiLliam Ken Allen

    细心如你一定已经发现了,当使用gsub函数时,gsub会替换指定范围内的所有符合条件的字符。

    而使用sub函数则不同,当使用sub函数时,sub函数只会替换指定范围内第一次匹配到的符合条件的字符。

    我们可以把gsub函数的作用理解为指定范围内的全局替换。

    可以把sub函数的作用理解为指定范围内的单次替换,只替换第一次匹配到的字符。

    这就是sub函数与gsub函数的为唯一的不同之处。

     

    我们可以通过length函数,获取到指定字符串的长度,示例如下

    [root@server01 ~]# awk '{for(i=1;i<=NF;i++){print $i,length($i)}}' test11
    Allen 5
    Phillips 8
    Green 5
    Lee 3
    William 7
    Ken 3
    Allen 5

    如上例所示,我们输出了文本中每个单词的长度,其实,length函数可以省略传入的参数,即不指定任何字符换,当省略参数时,默认使用"$0"作为参数,示例如下。

    [root@server01 ~]# awk '{print $0,length()}'  test11
    Allen Phillips 14
    Green Lee 9
    William Ken Allen 17

    正如上例假所示,我们使用length函数,获取到了文本中每一行的长度。

     

    我们可以使用index函数,获取到指定字符位于整个字符串中的位置,示例如下

    [root@server01 ~]# awk '{print index($0,"Lee")}' test11
    0
    7
    0

    上例中,我们使用index函数,在每一行中咋找字符串"Lee",如果Lee存在于当前行,则返回字符串Lee位于当前行的位置,如果Lee不存在于当前行,则返回0,表示当前行并不存在Lee,如上图所示,第二行中包含Lee,而且Lee位于第二行的第7个字符的位置,所以返回数字7。

     

    在前文中,我们在总结数组时,提到过一个函数,借助这个函数可以动态的生成数组,而不用手动的设置数组中每个元素的值,没错,这个函数就是split函数。通过split函数,我们可以将指定的字符串按照指定的分割符切割,将切割后的每一段赋值到数组的元素中,从而动态的创建数组,示例如下。

    [root@server01 ~]# awk -v ts="大娃:二娃:三娃" 'BEGIN{split(ts,huluwa,":");for(i in huluwa){print huluwa[i]}}'
    大娃
    二娃
    三娃

    如上例所示,我们通过split函数,将字符串ts切割了,以":"作为分割符,将分割后的字符串保存到了名为huluwa的数组中,当我们输出数组中的元素时,每个元素的值为分割后的字符,其实,split函数也有对应的返回值,其返回值就是分割以后的数组长度,示例如下。

    [root@server01 ~]# awk -v ts="大娃:二娃:三娃" 'BEGIN{print split(ts,huluwa,":")}'
    3

    注意,被split函数分割后的数组的元素下标从1开始,不像其他语言中的数组下标是从0开始的,而且数组中元素输出的顺序可能与字符串中字符的顺序不同,原因在前文中已经说过了,如果我们想要按照顺序输出数组中的元素,可以使用如下方法。

    [root@server01 ~]# awk -v ts="qq te ab th" 'BEGIN{split(ts,arr," ");for(i in arr){print arr[i]}}'
    th
    qq
    te
    ab
    [root@server01 ~]# awk -v ts="qq te ab th" 'BEGIN{arrlen=split(ts,arr," ");for(i=1;i<=arrlen;i++){print i,arr[i]}}'
    1 qq
    2 te
    3 ab
    4 th

    我们先使用了split函数生成了数组,并且将split的返回值保存在变量arrlen中,然后利用for循环中变量的递增,顺序的输出了数组中的对应下标以及元素值,如果你不明白为什么,请参考前文。

    其他函数

    我们还能够通过asort函数根据元素的值进行排序,但是,经过asort函数排序过后的数组的下标将会被重置,示例如下

    [root@server01 ~]# awk 'BEGIN{t["a"]=66;t["b"]=88;t["c"]=3;for(i in t){print i,t[i]}}'
    a 66
    b 88
    c 3
    [root@server01 ~]# awk 'BEGIN{t["a"]=66;t["b"]=88;t["c"]=3;asort(t);for(i in t){print i,t[i]}}'
    1 3
    2 66
    3 88

    如上例所示,数组中元素的值均为数字,但是下标为自定义的字符串,通过asort函数对数组排序后,再次输出数组中的元素时,已经按照元素的值的大小进行了排序,但是,数组的下标也被重置为了纯数字,其实,asort还有一种用法,就是在对原数组元素值排序的同时,创建一个新的数组,将排序后的元素放置在新数组中,这样能够保持原数组不做任何改变,我们只要打印新数组中的元素值,即可输出排序后的元素值,示例如下。

    [root@server01 ~]# awk 'BEGIN{t["a"]=66;t["b"]=88;t["c"]=3;asort(t,newt);for(i in t){print i,t[i]}}'
    a 66
    b 88
    c 3
    [root@server01 ~]# awk 'BEGIN{t["a"]=66;t["b"]=88;t["c"]=3;asort(t,newt);for(i in newt){print i,newt[i]}}'
    1 3
    2 66
    3 88

    其实,asort函数也有返回值,它的返回值就是数组的长度,换句话说,asort的返回值就是数组中元素的数量,示例如下。

    [root@server01 ~]# awk 'BEGIN{t["a"]=66;t["b"]=88;t["c"]=3;len=asort(t,newt);for(i=1;i<=len;i++){print i,newt[i]}}'
    1 3
    2 66
    3 88

    理解完asort 函数,我们来认识一下asorti 函数,仔细看,是 asort 与 asorti

    使用asort 函数可以根据元素的值进行排序,而使用asorti 函数可以根据元素的下标进行排序。

    当元素的下标为字符串时,我们可以使用asorti 函数,根据下标的字母顺序进行排序,当元素的下标为数字时,我们就没有必要使用函数排序了,直接使用for循环即可排序,所以,此刻我们只考虑数组的下标为字符串时,怎样通过asorti 函数根据下标对数组进行排序。

     

    当数组的下标为字符串时,asorti 函数会根据原数组中的下标的字母顺序进行排序,并且将排序后的下标放置到一个新的数组中,并且asorti函数会返回新的数组的长度,示例如下

    [root@server01 ~]# awk 'BEGIN{t["z"]=66;t["q"]=88;t["a"]=3;for(i in t){print i,t[i]}}'
    z 66
    a 3
    q 88
    [root@server01 ~]# awk 'BEGIN{t["z"]=66;t["q"]=88;t["a"]=3;len=asorti(t,newt);for(i=1;i<=len;i++){print i,newt[i]}}'
    1 a
    2 q
    3 z

    如上例所示,asorti 函数根据数组t的下标排序后,创建了一个新的数组newt,newt中元素的值即为t数组下标的值,上例中,我们使用len变量保存了asorti函数的返回值,并且输出了最后排序后的新数组。

    那么,聪明如你,一定想到了,既然我们已经将t数组的下标排序输出了,那么我们一定可以根据排序后的下标再次输出对应的元素值,从而达到根据数组下标排序后,输出原数组元素的目的,示例如下。

    [root@server01 ~]# awk 'BEGIN{t["z"]=66;t["q"]=88;t["a"]=3;len=asorti(t,newt);for(i=1;i<=len;i++){print i,newt[i],t[newt[i]]}}'
    1 a 3
    2 q 88
    3 z 66

    上述过程,其实就是新数组负责排序老数组的下标,并将排序后的下标作为新数组的元素,而我们输出新数组元素的同时,又将新数组的元素值作为老数组下标,从而输出了老数组中的元素值,这句话好绕

    [root@server01 ~]# awk '{gsub("[a-z]","6",$1);print $0}' test11A6666 PhillipsG6666 LeeW666666 Ken Allen

  • 相关阅读:
    MyCat 监控与日志查看
    Python--day40--threading模块
    Python--day40--主线程和子线程代码讲解
    Python--day40线程理论
    Python--day39--进程池的回调函数callback
    Python--day39--进程池原理及效率测试
    Python--day39--管道和数据共享(面试可能会问到)
    Python--day38--JoinableQueue解决生产者消费者模型
    Python--day38---进程间通信--初识队列(multiprocess.Queue)之生产者,消费者模型
    NPOI vs EPPlus 导出Excel简单对比
  • 原文地址:https://www.cnblogs.com/liujunjun/p/14202168.html
Copyright © 2020-2023  润新知