linux--awk笔记1

    科技2022-08-18  113

    刚刚进入工作一个多月了,发现工作环境需要大量使用linux命令,趁着国庆假期补补课。 参考: https://awk.readthedocs.io/en/latest/chapter-one.html

    1.awk程序结构 pattern{action} awk的基本操作是一行一行扫描输入,搜索匹配模式的行,执行动作后进行下一行的读取。

    1) A 数学 80 2) B 语文 90 3) C 英语 87

    对于上述的表数据,

    $4 == 90 {print $2}

    将打印出第4个字段为90的名字,B。 也可以在多个文件上执行这些命令。

    awk '$3==0{print $2}' file1 file2

    当程序命令较短时,选择使用单引号包装。当程序过长时,则可将其写入到文件中。

    awk -f progfile optional list of input files #-f:表示从指定文件中获取程序

    小结 awk命令默认是读取文件的一行内容,并根据空格和制表符分成多个字段,其中一个字段是不包含任何空格或者制表符的连续字符序列。其中$0为整行字符,$1为第一个字段,$2为第二个字段。

    {print } #打印每一行内容 #or {print $0}

    2.awk的简单输出 利用print打印多个字段,

    {print $1, $3}

    打印第一个和第三个字段,中间用空格分离,最后用回车符号结尾。如下所示,

    1) 数学 2) 语文 3) 英语

    字段数量 awk命令会对一行的多少个字段数进行计数,并将其存储在一个叫做NF的变量中。

    {print NF, $1$NF} #打印字段数目,以及第一个和最后一个字段

    字段的计算

    {print $1, $2*$3}

    行号 变量NR,存储行的计数。

    {print NR, $0}

    能够为每一行加上行号.

    添加内容 双引号中内容将添加到输出内容中。

    {print "total pay for", $1, "is","$2*$3"}

    格式化输出 若要严格按照需要的格式化输出,则需要使用printf语句。 printf语句形式:

    printf(format, value1, value2, ... valuen)

    如:

    {printf("total pay for %s is %.2f\n", $1, $2*$3)}

    其中%s表示以字符串方式打印第一个字段,第二个以数字打印,并保留小数点后2位数字,结尾需要回车来创建行。

    {printf("%-8s %6.2f\n", $1, $2*$3)}

    第一个规格%-8s,将第一个字段在8个字符宽度的字段中左对齐输出。第二个规格%6.2f将字段2以数字形式,保留小数点后两位,以6字符宽度的字段中进行输出。

    awk '{ print("%6.2f, %s\n", )}'

    递增方式打印 排序方式输出

    awk '{printf("%6.2f %s\n",$2*$3, $0)}' filename |sort

    将awk的输出通过管道传输给sort命令,按照$2*$3字段递增方式排序。

    3.数据选择

    $2*$3>50 {printf("$%.2f for %s\n", $2*$3, $1)} #根据>50的条件筛选字段 $1 == "Susie" #根据==号筛选字符串

    模式组合,通过括号和&&,||,!来对模式进行组合。 两个条件都满足的打印一次

    $2 >= 4 || $3 >= 20

    打印既不满足$2<4也不满足$3<20的行

    !($2 < 4 && $3 < 20)

    数据验证

    'NF!=3 {print $0, "number is not equal to 3"}'

    BEGIN与END BEGIN匹配第一个输入文件第一行之前的位置,END用于匹配最后一个文件最后一行的位置。 如下,使用Begin匹配一个标题: 程序动作部分可加多个语句,但是需要用分行隔开。 普通的print是打印当前输入行,但是print ""则是打印一个空行。

    BEGIN {print "Name RATE HOUR"; print ""} {print}

    4.数值计算 统计第3个字段大于15的值,如果不加END,每读取一行就打印一次计数,加END打印最后的一次计数。

    $3 >15 {emp = emp + 1} END {print emp, "more than 15"}

    计算行数

    NR {print NR, "numbers"}

    处理文本

    $2 > maxscore {maxscore=$4; maxname=$2} END {print "maxscore is",maxscore,"for",maxname}

    程序中变量maxscore保留着数字,maxname保留着字符串。

    字符串拼接

    {names=names $2 " "} END {print names}

    首先初始化一个names,为空字符串,然后再使用第一行的第二个字段和空格进行拼接。最后打印所有的字符串。其中用于保存字符串变量names的默认初始值为空字符串,不需要显示初始化。

    打印最后一行

    {last = $0} END {print last}

    测试了一下,$0也能打印出最后一行的结果。

    END {print $0}

    length(…) 统计字符串长度内置函数

    {print $1, legnth($1)}

    统计行数,单词书(字段数),字符数

    {nc = nc + length($0) +1 #加了每行的换行符 nw = nw + NF} END {print NR, "lines,", nw "words," nc, "characters"}

    控制语句 if-else语句,需要在action中使用。

    $2>6,{n=n+1;pay=pay+$2*$3} END {if(n>0) print n else print "0" }

    可在语句中使用逗号将长语句进行截取。 while

    # interest1 - 计算复利 # 输入: 钱,利率,年数 # 输出: 复利值 { i=1 while (i<=$3) { printf("\t %.2f\n",$1*(1+$2)^i) i=i+1 } }

    for循环 循环体只是一句语句,因此不需要用大括号来包围它。

    { for(i=1;i<=$3;i=i+1) printf("\t%.2f\n",$1*(1+$2)^i) }

    数组 写到统一行记得用;隔开

    #逆序打印输入 {line[NR]=$0} END { i=NR while(i>0){ print line[i] i=i-1 } }

    改成for循环,同一行记得用分号隔开啊,今天的就到这里了。

    {line[NR]=$0} END {for(i=NR;i >0;i--) print line[i]}
    Processed: 0.008, SQL: 9