很高兴和你相遇
这里正在记录我的所思所学
订阅免费邮件通讯接收最新内容
首页 归档 想法 工具 通讯 播客 简历 主页

awk 入门与进阶 part1—快速入门

awk 的结构

由一个单独的模式–动作语句 (pattern-action statement) 组成。

pattern{ action }

awk 的运行方式

awk 的基本操作是在由输入行组成的序列中,陆续地扫描每一行,搜索可以被模式匹配 (match) 的行。每一个输入行轮流被每一个模式测试。每匹配一个模式,对应的动作(可能包含多个步骤) 就会执行。然后下一行被读取,匹配重新开始。这个过程会一起持续到所有的输入被读取完毕为止。

执行 awk 方式

  • awk+执行语句+文件

awk 'program' input files

  • awk+执行语句

在命令行上省略输入文件,在这种情况下,awk 会将 program 应用到接下来在终端输入的内容,直到键入文件结束标志 ctrl-d。

  • awk+脚本

awk -f progfile optional list of files

入门应知

输出

awk 从输入中每次读取一行,将行分解为一个个的字段(默认将字段看作是非空白字符组成的序列)。当前输入行的第一个字段叫作、$1,第二个是、$2,依次类推。一整行记为$0。每行的字段数有可能不同。

print 打印当前输出行,$0 表示整行,$1 表示第一个字段。在 print 语句中由逗号分隔的表达式,在输出时默认用一个空格符分隔。Awk 计算当前输入行的字段数量,并将它存储在一个内建的变量中,这个变量叫作 NF。$NF 表示打印最后一个字段。

用字段的值进行计算,并将计算得到的结果放在输出语句中。如{print $1*$2}

另一个内建变量** NR**,这个变量计算到目前为止,读取到的行的数量。我们可以使用 NR 来表示行号。添加行号写法{ print NR, $0 }。添加文本,引号包围的文本会和字段和运算结果一起输出。

修改输出格式可以试用 printif。使用格式printf(format, value1, value2, ..。, valuen) format 是一个字符串,包含按字面打印的文本,中间包括格式说明符,格式说明符用于说明如何打印值。一个格式说明符是一个%,后面跟着几个字符控制一个 value 的输出格式。第一个格式说明符说明 value1 的输出格式,第二个格式说明符说明 value2 的输出格式,依次类推。使用 printf 不会自动产生空格符或换行符必须自己添加、n。

选择

通过比较和计算或者文本可以选择输出感兴趣的行。

$1 >= 5
$1+$3 > 10
$1=="chr1"

结合逻辑运算符进行组合选择。

|| or; && and; ! not

数据验证

真实的数据总是存在错误,检查数据是否具有合理的值,格式是否正确,通常称作数据验证 (data validation),数据验证的本质是否定,也就是说打印出可以的行。比如想验证是不是每一行都有 4 列,即可以使用NF != 4 {print $0}

BEGIN END

特殊的模式 BEGIN 在第一个输入文件的第一行之前被匹配,END 在最后一个输入文件的最后一行被处理之后匹配。

计算

#计数:
awk '$2>1{num=num +1}END{print num}' awk.txt
#总数
awk 'END{print NR}' awk.txt
#平均数
awk '{sum=sum + $2}END{print sum/NR}' awk.txt
# 输出最大值(变量可以是字符串)
awk '$2 > max { max = $2; maxid = $1 }END { print max, maxid }' awk.txt
# 字符串拼接
awk '{id = id $1 " " }END { print id }' awk.txt
#字符个数 length
awk '{ print $3,length($3) }' awk.txt

流程控制

if-else

awk '
{ n = $2; id =$1 }
END { if (n > 333)
print n,id
else print "< 333"
}' awk.txt

for:大多数循环都包括初始化,测试,增值,而 for 语句将这三者压缩成一行。

awk '
{ for(i=1;i<= NR; i=i+1)
    print i,$2' awk.txt

while:while 含有一个条件判断与一个循环体。当条件为真时,循环体执行。

awk '{ i = 1
while (i <= NR) {
    print i, $1
        i = i + 1
    }
}' awk.txt

while 后面被括号包围起来的表达式是条件判断;循环体是跟在条件判断后面的,被花括号包围起来的的两条语句。

数组

Awk 提供了数组用来存储一组相关的值。

#逆序显示
awk'{ line[NR] = $0 } # remember each input line
END { i = NR # print lines in reverse order
    while (i > 0) {
        print line[i]
        i = i - 1
    }
}' awk.txt

awk'
{ line[NR] = $0 } # remember each input line
END { for (i = NR; i > 0; i = i - 1)
print line[i]
}'

awk 常用一行命令

#1. 输入行的总行数
END { print NR }
#2. 打印第 10 行
NR == 10
#3. 打印每一个输入行的最后一个字段
{ print $NF }
#4. 打印最后一行的最后一个字段
{ field = $NF }
END { print field }
#5. 打印字段数多于 4 个的输入行
NF > 4
#6. 打印最后一个字段值大于 4 的输入行
$NF > 4
#7. 打印所有输入行的字段数的总和
{ nf = nf + NF }
END { print nf }
#8. 打印包含 Beth 的行的数量
/Beth/ { nlines = nlines + 1 }
END { print nlines }
#9. 打印具有最大值的第一个字段,以及包含它的行(假设$1 总是正的)
$1 > max { max = $1; maxline = $0 }
END { print max, maxline }
#10. 打印至少包含一个字段的行
NF > 0
#11. 打印长度超过 80 个字符的行
length($0) > 80
#12. 在每一行的前面加上它的字段数
{ print NF, $0 }
#13. 打印每一行的第 1 与第 2 个字段,但顺序相反
{ print $2, $1 }
#14. 交换每一行的第 1 与第 2 个字段,并打印该行
{ temp = $1; $1 = $2; $2 = temp; print }
#15. 将每一行的第一个字段用行号代替
{ $1 = NR; print }
#16. 打印删除了第 2 个字段后的行
{ $2 = ""; print }
#17. 将每一行的字段按逆序打印
{ for (i = NF; i > 0; i = i - 1) printf("%s ", $i)
printf("\n")
}
#18. 打印每一行的所有字段值之和 D
{ sum = 0
for (i = 1; i <= NF; i = i + 1) sum = sum + $i
print sum
}
#19. 将所有行的所有字段值累加起来
{ for (i = 1; i <= NF; i = i + 1) sum = sum + $i }
END { print sum }
#20. 将每一行的每一个字段用它的绝对值替换
{ for (i = 1; i <= NF; i = i + 1) if ($i < 0) $i = -$i
print
}

本文作者:思考问题的熊

版权声明:本博客所有文章除特别声明外,均采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 (CC BY-NC-ND 4.0) 进行许可。

如果你对这篇文章感兴趣,欢迎通过邮箱或者微信订阅我的 「熊言熊语」会员通讯,我将第一时间与你分享肿瘤生物医药领域最新行业研究进展和我的所思所学所想点此链接即可进行免费订阅。


· 分享链接 https://kaopubear.top/blog/2018-06-01-awk1/