awk - 数据提取和报告工具 (3) 函数

  • 原创
  • Madman
  • /
  • 2018-04-14 09:15
  • /
  • 0
  • 300 次阅读

awk - 数据提取和报告工具 (3) 函数-min.png

Synopsis: 列举了awk中常用的内置函数,以及如何创建自定义函数。内置函数大致可以分成5类,算术运算相关的函数,字符串操作相关函数,时间处理相关函数,位运算相关函数,以及其它特殊功能函数。awk也支持用户自己定义函数结构,类似于shell中的函数。作为一门编程语言,函数是功能的提取,可以大幅度缩短awk脚本的大小

awk系列:


1. 常用内置函数

1.1 算术函数

(1) int(expr)

将数字转换成整数

# awk 'BEGIN { print int(4.1); print int(-6.22); print int(strings) }'

(2) rand()srand([expr])

rand()返回0至1之间的随机数;srand([expr]) 一般配合rand()一起使用,设置产生随机数时使用的种子

1. rand()每次使用相同的随机种子 1 ,所以产生的随机数一样
# awk 'BEGIN { print rand(),rand(),rand(); }'
0.237788 0.291066 0.845814
# awk 'BEGIN { print rand(),rand(),rand(); }'
0.237788 0.291066 0.845814

2. 使用srand()来改变随机种子
# awk 'BEGIN { srand(1); print rand(),rand(),rand(); }'
0.237788 0.291066 0.845814
# awk 'BEGIN { srand(2); print rand(),rand(),rand(); }'
0.610198 0.661343 0.872396
# awk 'BEGIN { srand(); print rand(),rand(),rand(); }'
0.679712 0.571719 0.884189

其它函数:

  • atan2(y, x) 反正切函数
  • cos(expr) 余弦函数
  • sin(expr) 正弦函数
  • exp(expr) 以自然对数e为底指数函数
  • log(expr) 计算以e 为底的对数值
  • sqrt(expr) 绝对值函数

1.2 字符串函数

(1) index(s, t)

返回字符串t在s中第一次出现的位置,下标位置是从1开始计算的,如果没有找到则返回0

# awk 'BEGIN{ s="My name is wangy"; print index(s, "y"); }'
2
# awk 'BEGIN{ s="My name is wangy"; print index(s, "is"); }'
9
# awk 'BEGIN{ s="My name is wangy"; print index(s, "z"); }'
0

(2) length([s])

返回字符串的长度,如果参数s没有指定,默认使用$0

# awk 'BEGIN { print length("My name is wangy") }'
16
# echo "My name is wangy" | awk 'BEGIN { RS=" " } { print length() }'
2
4
2
6

(3) match(s, r [, a])

判断子字符串r是否匹配字符串s,如果匹配返回r在s中的起始位置,如果不匹配则返回0。 该函数定义了RSTART和RLENGTH两个内置变量:

  • RSTART 当匹配时,返回匹配的开始位置;否则返回0
  • RLENGTH 当匹配时,返回匹配串的长度;否则返回-1
# awk 'BEGIN { s="My name is wangy"; if(res=match(s, "wang")){ printf("Matched at: %d, matched substr length: %d\n", RSTART, RLENGTH); } else { print "Not matched, the result is:", res, ", and RLENGTH is:", RLENGTH }}' 
Matched at: 12, matched substr length: 4

# awk 'BEGIN { s="My name is wangy"; if(res=match(s, "yang")){ printf("Matched at: %d, matched substr length: %d\n", RSTART, RLENGTH); } else { print "Not matched, the result is:", res, ", and RLENGTH is:", RLENGTH }}' 
Not matched, the result is: 0 , and RLENGTH is: -1

# awk 'BEGIN { s="My name is wangy"; if(match(s, "wang")){ print substr(s, RSTART, RLENGTH) } }' 
wang

(4) split(s, a [, r [, seps] ])

将字符串s按照分隔符seps,分隔成多个部分,并存到数组a中,存放的位置从1开始,返回数组a的元素个数。如果seps为空,则默认使用FS分隔

# echo "arg1:arg2:arg3" | awk '{ lens=split($0, a, ":"); for (i in a) print a[i]; print "\nThe length of a is:", lens }'
arg1
arg2
arg3
The length of a is: 3

(5) sub(r, s [, t])

将字符串 t 中匹配 r 的部分替换成 s (会修改字符串 t),只替换第一个符合项。如果省略 t ,默认使用$0

# awk 'BEGIN { t="ThIs is test"; sub("[Ii]s","e", t); print t; }'
The is test

(6) gsub(r, s [, t])

将字符串 t 中匹配 r 的部分替换成 s (会修改字符串 t),全局替换。如果省略 t ,默认使用$0

# awk 'BEGIN { t="ThIs is test"; gsub("[Ii]s","e", t); print t; }'
The e test

(7) substr(s, i [, n])

返回字符串 s 中从位置 i 开始,长度为 n 的子串(注意:字符串起始位置为 1),如果未指定 n 或者 n 大于剩余的字符个数,则一直截取到字符串 s 的末尾

# awk 'BEGIN { print substr("Microsoft", 6, 2); }'
so
# awk 'BEGIN { print substr("Microsoft", 6); }'
soft

(8) tolower(str)toupper(str)

1. 把字符串转换为小写
# awk 'BEGIN { print tolower("Microsoft"); }'
microsoft

2. 把字符串转换为大写
# awk 'BEGIN { print toupper("Microsoft"); }'
MICROSOFT

(9) asort

asort函数会对数组的值进行排序,丢弃原先的键(即原key=>value的关系被破坏),并返回数组的长度

# cat array_asort.awk 
BEGIN{  
    s = "My,name,is,wangy";   
    lens = split(s, a, ",");   
    print "The length of array a is:", lens;  
    print "--- for in (unordered) ---"; 
    for(k in a){  
        print "Key:",k,"\tValue:",a[k];  
    }  
    print "--- for (ordered) ---"  
    for(k=1; k<=lens; k++){  
        print "Key:",k,"\tValue:",a[k];  
    }  
    # output newline
    print;
    print "--- after asort ---"  
    print "asort(a), this return the length of new array:", asort(a);
    # output newline
    print;
    print "--- for in (unordered) ---"  
    for(k in a){  
        print "Key:",k,"\tValue:",a[k];  
    }  
    print "--- for (ordered) ---"  
    for(k=1; k<=lens; k++){
        print "Key:",k,"\tValue:",a[k];  
    }
}

# awk -f array_asort.awk 
The length of array a is: 4
--- for in (unordered) ---
Key: 4  Value: wangy
Key: 1  Value: My
Key: 2  Value: name
Key: 3  Value: is
--- for (ordered) ---
Key: 1  Value: My
Key: 2  Value: name
Key: 3  Value: is
Key: 4  Value: wangy
--- after asort ---
asort(a), this return the length of new array: 4
--- for in (unordered) ---
Key: 4  Value: wangy
Key: 1  Value: My
Key: 2  Value: is
Key: 3  Value: name
--- for (ordered) ---
Key: 1  Value: My
Key: 2  Value: is
Key: 3  Value: name
Key: 4  Value: wangy

(10) asorti

asorti函数会对数组的键排序,当你排序后需要保存数组的键时使用。返回数组的长度

# cat test.txt 
101 Microsoft
303 Adobe
202 Google

# cat asorti.awk 
{
    # create the array item
    item[$1] = $2
}
END {
    print "----- Function: asort -----";
    lens = asort(item, asort_arr);
    for (i=1; i<=lens; i++) {
        print "Index of asort_arr:",i,"\tKey:",i,"\tValue:",asort_arr[i];
    }
    # output newline
    print "\n";
    print "----- Function: asorti -----";
    lens2 = asorti(item, asorti_arr);
    for (i=1; i<=lens2; i++) {
        print "Index of asorti_arr:",i,"\tKey:",asorti_arr[i],"\tValue:",item[asorti_arr[i]];
    }
}

1.3 时间函数

(1) strftime([format [, timestamp[, utc-flag]]])

此函数返回当天的当前时间,即自Epoch(POSIX系统的1970-01-01 00:00:00 UTC)以来的秒数

# awk 'BEGIN { print "Number of seconds since the Epoch = " systime() }'
Number of seconds since the Epoch = 1473439158

(2) mktime(datespec)

该函数将datespec字符串转换为与systime()返回的形式相同的时间戳。 datespec是一个形式为YYYY MM DD HH MM SS的字符串

# awk 'BEGIN { print "Number of seconds since the Epoch = " mktime("2016 09 14 16 52 00") }'
Number of seconds since the Epoch = 1473843120

(3) strftime([format [, timestamp[, utc-flag]]])

格式化时间戳。 如果utc-flag存在并且非零或非空,则结果以UTC为单位,否则结果将在本地时间。 时间戳应该与systime()返回的格式相同。 如果缺少时间戳,则使用当前的一天中的时间

# awk 'BEGIN { print "Now time is:" strftime("%a %b %d %H:%M:%S %Z %Y", systime()) }'
Now time is:Wed Sep 14 16:57:06 CST 2016

1.4 位运算函数

  • and 按位与
  • or 按位或
  • xor 按位异或
  • lshift 按位左移
  • rshift 按位右移
# cat bits.awk 
BEGIN {
    number1=15
    number2=25
    print "AND: " and(number1,number2);
    print "OR: " or(number1,number2);
    print "XOR: " xor(number1,number2);
    print "LSHIFT: " lshift(number1,2);
    print "RSHIFT: " rshift(number1,2)
}
# awk -f bits.awk 
AND: 9
OR: 31
XOR: 22
LSHIFT: 60
RSHIFT: 3

1.5 其它函数

(1) system

该函数执行指定的命令并返回其退出状态。 返回状态0表示命令执行成功。 非零值表示命令执行失败。 例如,以下示例显示当前日期并显示命令的返回状态

# awk 'BEGIN { ret = system("date"); print "Return value = " ret }'
Wed Sep 14 17:12:46 CST 2016
Return value = 0

(2) getline [var]

该函数指示awk读取下一条记录(默认为下一行)。如果后面有变量 var,把下一条记录存储到 var,否则替换$0

# cat score.txt
1) Amit     Physics   80
2) Rahul    Maths     90
3) Shyam    Biology   87
4) Kedar    English   85
5) Hari     History   89

# awk '{ getline; print $0 }' score.txt
2) Rahul    Maths     90
4) Kedar    English   85
5) Hari     History   89

# awk '{ getline tmp; print "$0  -> ", $0; print "tmp -> ", tmp; }' score.txt 
$0  ->  1) Amit     Physics   80
tmp ->  2) Rahul    Maths     90
$0  ->  3) Shyam    Biology   87
tmp ->  4) Kedar    English   85
$0  ->  5) Hari     History   89
tmp ->  4) Kedar    English   85

(3) close(expr)

关闭管道文件

# cat myscript.awk
BEGIN {
    if (("date" | getline date_now) <= 0) {
        print "Can't get system date" > "/dev/stderr"
        exit 1
    }
    print "current date is", date_now
    close("date")
}

# awk -f myscript.awk
current date is Wed Sep 14 16:57:06 CST 2016

(4) next

# awk '{if ($0 ~/Shyam/) next; print $0}' score.txt 
1) Amit     Physics   80
2) Rahul    Maths     90
4) Kedar    English   85
5) Hari     History   89

(5) nextfile

# cat file1.txt 
file1:str1
file1:str2
file1:str3
# cat file2.txt 
file2:str1
file2:str2
file2:str3

# awk '{ if ($0 ~ /file1:str2/) nextfile; print $0 }' file1.txt file2.txt
file1:str1
file2:str1
file2:str2
file2:str3

(6) return

用户自定义函数的返回值

# vim myscript.awk

内容如下:
function addition(num1, num2) {
   result = num1 + num2
   return result
}
BEGIN {
   res = addition(10, 20)
   print "10 + 20 = " res
}

# awk -f myscript.awk
10 + 20 = 30

(7) exit

exit 停止执行awk程序,可选参数expr,用以表示awk的返回值

# awk 'BEGIN { print "Hello, World !!!"; exit 10; print "AWK never executes this statement." }'
Hello, World !!!
# echo $?
10

2. 自定义函数

1. 创建包含awk程序的外部文件
# vim user-defined-functions.awk

内容如下:
# Returns minimum number
function find_min(num1, num2){
   if (num1 < num2)
   return num1
   return num2
}
# Returns maximum number
function find_max(num1, num2){
   if (num1 > num2)
   return num1
   return num2
}
# Main function
function main(num1, num2){
   # Find minimum number
   result = find_min(10, 20)
   print "Minimum =", result

   # Find maximum number
   result = find_max(10, 20)
   print "Maximum =", result
}
# Script execution starts here
BEGIN {
   main(10, 20)
}

2. 执行
# awk -f user-defined-functions.awk 
Minimum = 10
Maximum = 20
分类: Linux
标签: awk gawk GNU
未经允许不得转载: LIFE & SHARE - 王颜公子 » awk - 数据提取和报告工具 (3) 函数

分享

作者

作者头像

Madman

如果博文内容有误或其它任何问题,欢迎留言评论,我会尽快回复; 或者通过QQ、微信等联系我

0 条评论

暂时还没有评论.

发表评论前请先登录

专题