0%

awk高级用法

总结awk中使用内置函数以及if-else、for循环等用法。

awk中除了一些内置函数之外,也可以与其他函数结合在一起使用实现一些复杂的用法。

1. awk中内置函数

函数 函数作用 用法 命令输出
length($0) 输出$0的长度 echo "hello" | awk '{print length($0)}' 5
substr(str,start,length) 返回字符串中从start位置开始长度为length的子串 echo "hello world" | awk '{print substr($0,7,5)}' world
index(str,sub) 返回str字符串中第一次出现子串sub的位置,如果没有匹配,返回0 echo "hello" | awk '{print index($0,"world")}' 7
split(str,arr,sep) 将字符串按照分隔符sep分隔成数组arr echo "1,2,3,4" | awk '{split($0,arr,",");print arr[3]}' 3
gsub(regexp,replacement,str) 用字符串replacement替换字符串str中所有匹配正则表达式regexp的子串 echo "hello world" | awk '{gsub(/o/,"O",$0);print}' hellO wOrld
six(x)、cos(x)、tan(x)、exp(x)、log(x)、sqrt(x) 数学函数,计算正弦值、余弦值、正切值、指数函数、对数、平方根 echo "3.1415926" | awk '{print sin($0)}' 0.001592665
sstrftime(format,timestamp) 将时间戳timestamp格式转换为指定的日期格式 echo $(date +%s) | awk '{print strftime("%Y-%m-%d %H:%M:%S", $1)}' 输出当前时间的日期格式2023-05-02 12:24:59
tolower($0)、toupper($0) 将字符串转换为大/小写 echo "hello world" | awk '{print toupper($0)}' HELLO WORLD

2. awk中使用控制语句:if-else条件语句/for循环/while循环/do-while循环

  • if/else 条件语句:可以根据指定的条件执行不同的操作。

    1
    awk '{if($1 > 10) {print "large"} else {print "small"}}' file.txt

    上面的命令根据第一个字段的值输出 “large” 或 “small”。

  • for 循环:可以使用 for 循环对指定的字段进行遍历。

    1
    awk '{for(i=1; i<=NF; i++) {print $i}}' file.txt

    上面的命令遍历每个字段并输出。

  • while 循环:可以使用 while 循环对指定的条件进行迭代。

    1
    awk '{i=1; while(i<=NF) {print $i; i++}}' file.txt

    上面的命令使用 while 循环遍历每个字段并输出。

  • do/while 循环:可以使用 do/while 循环对指定的操作进行迭代,直到满足指定的条件为止。

    1
    awk '{i=1; do {print $i; i++} while(i<=NF)}' file.txt

    上面的命令使用 do/while 循环遍历每个字段并输出。

3. awk中使用数组

awk 中,数组是一种非常有用的数据结构,可以用于存储和处理文本数据。awk 中的数组是关联数组,也就是说,数组的下标可以是任意字符串或数字。

以下是 awk 中使用数组的示例:

  1. 声明和初始化数组:

    1
    awk 'BEGIN{arr["apple"]=1; arr["orange"]=2; arr["banana"]=3; print arr["apple"], arr["orange"], arr["banana"]}' file.txt

    上面的命令中,声明了一个名为 arr 的数组,并初始化了三个元素,然后输出了这些元素的值。

  2. 遍历数组:

    1
    awk 'BEGIN{arr["apple"]=1; arr["orange"]=2; arr["banana"]=3; for(i in arr) {print i, arr[i]}}' file.txt

    上面的命令中,使用 for 循环遍历了 arr 数组,并输出了数组中每个元素的下标和值。

  3. 使用数组进行计数:

    1
    awk '{count[$1]++} END{for(i in count) {print i, count[i]}}' file.txt

    上面的命令中,每次处理一行时,将第一个字段作为数组 count 的下标,并将对应的元素加 1。在处理完所有行后,使用 for 循环遍历 count 数组,并输出每个元素的下标和值,从而实现对每个值出现次数的计数。

以上是 awk 中使用数组的示例,数组在 awk 中的使用非常灵活,可以根据需要进行不同的操作。

4. awk分隔符

  1. 使用多个分隔符
    awk默认使用空格或tab为分隔符,使用多个分隔符时,用-F参数指定
    1
    awk -F '[,;]' '{print $1,$2,$3}' file.txt
  2. 自定义输出分隔符
    使用OFS变量定义自定义输出分隔符:
    1
    awk 'BEGIN{OFS=","} {print $1,$2,$3}' file.txt
  3. 使用正则表达式
    使用正则表达式匹配文本:
    1
    awk '/pattern/{print $1,$2}' file.txt
    输出文件中包含pattern的行的第一列和第二列。

5. awk高级用法实例

有一个test文件内容如下:

1
2
3
4
5
6
7
cat test
1 3
1 4
1 5
2 2
2 5
2 3

利用awk根据第一列值的不同进行分组,求第二列在相应组别中所占的比例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
awk 'BEGIN{
while (getline < "test")
{
a[$1]+=$2
}
close("test")
while (getline < "test")
{
for (i in a)
{
if ($i==i)
{ print $1,$2,a[i],$2/a[i] }
}
}
close("test")
}'

结果:

1
2
3
4
5
6
1 3 12 0.25
1 4 12 0.333333
1 5 12 0.416667
2 2 10 0.2
2 5 10 0.5
2 3 10 0.3

需要将文件遍历两遍,第一遍根据不同的分组计算不同组别的总和(求不同分组的和必然要将文件每一行都遍历一遍),第二遍求每一行相应数据所占的比例。所以需要将该文件遍历两遍,awk中将文件遍历两遍,可以使用getline函数。geline类似于python中的readline,一行一行地读取数据,最后遍历完之后将求得的和存入数组,然后关闭文件再重新进行第二遍的读取。

第一列是字符串时也适用:

1
2
3
4
5
6
7
cat test
a 3
a 4
b 5
b 2
c 5
c 3

结果如下:

1
2
3
4
5
6
a 3 7 0.428571
a 4 7 0.571429
b 5 7 0.714286
b 2 7 0.285714
c 5 8 0.625
c 3 8 0.375