shell脚本学习指南[四](Arnold Robbins & Nelson H.F. Beebe著)

2019-09-23 09:42:05丽君

#要从文本文件里随机打印5%行左右的样本:
awk 'rand() < 0.05 ' file(s)
#以空白分隔字段的表格中,报告第n栏的和:
awk -v COLUMN=n '{ sum += $COLUMN } END { print sum } ' file(s)
#产生字段n栏的平均值
awk -v COLUMN=n '{ sum += $COLUMN } END { print sum / NR } ' file(s)
#统计文件最后一个字段的总数
awk '{ sum += $NF; print $0 , sum }' file(s)
#三种查找文件内文本的方式:
egrep 'pattern|pattern' file(s)
awk '/pattern|pattern/' file(s)
awk '/pattern|pattern/ { print FILENAME ":" FNR ":" $0 }' file(s)
#仅查找100-150行 的匹配信息
sed -n -e 100,150p -s file(s) | egrep 'pattern'
awk '(100<=FNR)&&(FNR<=150)&& /pattern/ { print FILENAME":"FNR":"$0}' file(s)
#要在四栏表格里调换二三栏,假设制表符分隔:
awk -F't' -v OFS='t' '{ print $1,$3,$2,$4}' old > new
awk 'BEGIN {FS=OFS='t' } {print $1,$3,$2,$4 }' old > new
awk -F't' '{ print $1 "t"$3"t"$2"t"$4} ' old > new
#将格栏分隔符由制表符替换成&:
sed -e 's/t/&/g' file(s)
awk 'BEGIN { FS="t"; OFS="&" } {$1 = $1; print }' file(s)
#删除排序后的重复行:
sort file(s) | uniq
sort file(s) | awk 'Last != $0 { print } {Last = $0} '
#将回车字符/换行符的行终结,一致转换为以换行字符为行终结:
sed -e 's/r$//' file(s)
sed -e 's/^M$//' file(s)
mawk 'BEGIN { RS="rn" } { print } ' file(s)
#找出长度超过72个字符的行:
egrep -n '^.{73,}' file(s)
awk 'length($0) > 72 { print FILENAME":"FNR":"$0}' file(s)

awk支持语句的连续执行。支持条件语句,if else 类似C语言,支持循环 while(){} 或do{} while()或for( ; ; ){] 类似c语言。还有一个for(key in array) { } 。
如 awk 'BEGIN { for( x=0; x<=1;x+=0.05) print x}' 。虽然很多类似C,但是注意awk中是缺乏逗点运算符的。循环同样可以使用break和continue 。

awk直接处理命令行上标明的输入文件,一般不用用户自己打开与处理文件,但是也可以通过awk的getline语句做这些事情。用法:
getline 从当前输入文件读取下一条记录存入$0,并更新NF、NR、FNR
getline var 从当前输入文件中,读取下一条记录存入var并更新NR、FNR
getline < file 从fle中读取下一条记录,存入$0,并更新NF
getline var < file 从file读取下条记录存入var
cmd | getline 从外部命令cmd读取下条记录存入$0,并更新NF
cmd | getline var 从外部命令读取下条记录,存入var
如果像确保来自控制终端的输入则:getline var < "/dev/tty"

在awk里可以通过管道与外部的shell命令混写:


tmpfile = "/tmp/telephone.tmp"
comman = "sort > " tmpfile
for ( name in telephone)
    print name "t" telephone[name] | command
close (command)
while((getline < tmpfile) > 0)
   print
close(tmpfile)