• 十,awk内置函数


      在awk中,可以自定义函数,也有内置的函数,今天我们就来总结一些常用的内置函数。

       awk的内置函数大致可以分类为算数函数、字符串函数、时间函数、其他函数等

      

      算数函数

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

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

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

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

    [root@node1 ~]# awk 'BEGIN{srand();print rand()}'
    0.100419
    [root@node1 ~]# awk 'BEGIN{srand();print rand()}'
    0.691322
    [root@node1 ~]# awk 'BEGIN{srand();print rand()}'
    0.355234
    [root@node1 ~]# awk 'BEGIN{srand();print rand()}'
    0.355234
    [root@node1 ~]# 
    

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

    [root@node1 ~]# awk 'BEGIN{srand();print rand()}'
    0.563365
    [root@node1 ~]# awk 'BEGIN{srand();print 100*rand()}'
    13.1234
    [root@node1 ~]# awk 'BEGIN{srand();print int(100*rand())}'
    71
    [root@node1 ~]#
    

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

      字符串函数

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

      

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

    [root@node1 ~]# cat test11
    Allen Phillips
    Green Lee
    William Ken Allen
    [root@node1 ~]# 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
    [root@node1 ~]# 
    

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

    [root@node1 ~]# awk '{print length()}' test11
    14
    9
    17
    [root@node1 ~]# awk '{print length($0)}' test11
    14
    9
    17
    [root@node1 ~]# 
    

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

    [root@node1 ~]# awk '{print index($0,"Lee")}' test11 
    0
    7
    0
    [root@node1 ~]# cat test11
    Allen Phillips
    Green Lee
    William Ken Allen
    [root@node1 ~]# 
    

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

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

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

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

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

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

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

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

    [root@node1 ~]# 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@node1 ~]# 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
    [root@node1 ~]# 
    

     

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

    [root@node1 ~]# 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
    [root@node1 ~]# 
    

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

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

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

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

    [root@node1 ~]# awk 'BEGIN{t["z"]=66;t["q"]=88;t["a"]=3;len=asorti(t,newt);for(i=1;i<=len;i++) {print i,t[i]}}'
    1 
    2 
    3 
    [root@node1 ~]# 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@node1 ~]# 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
    [root@node1 ~]# 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@node1 ~]# 
    

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



      

  • 相关阅读:
    Spring Boot 使用 Dom4j XStream 操作 Xml
    Spring Boot 使用 JAX-WS 调用 WebService 服务
    Spring Boot 使用 CXF 调用 WebService 服务
    Spring Boot 开发 WebService 服务
    Spring Boot 中使用 HttpClient 进行 POST GET PUT DELETE
    Spring Boot Ftp Client 客户端示例支持断点续传
    Spring Boot 发送邮件
    Spring Boot 定时任务 Quartz 使用教程
    Spring Boot 缓存应用 Memcached 入门教程
    ThreadLocal,Java中特殊的线程绑定机制
  • 原文地址:https://www.cnblogs.com/minseo/p/13690129.html
Copyright © 2020-2023  润新知