zoukankan      html  css  js  c++  java
  • linux-文本处理-awk

    awk

    格式

    #program表示脚本,短的脚本可以直接在命令行中使用
    awk 'program' input-file1 input-file2 ...
    #长的脚本则可以使用单独的脚本文件
    awk -f program-file input-file1 input-file2 
    

    简单示例

    awk 'BEGIN { print "hello world" }'
    

    脚本必须使用{}大括号,有些示例可以不加BEGIN,但在wsl中不用BEGIN会不执行

    独立可执行的awk文件

    #! /bin/awk -f
    BEGIN { print "Don't Panic!" }
    

    此单独的awk文件可以单独执行,不需要使用上面awk -f program-file的格式。

    注意:

    awk文件需要执行chmod +x filename,授予可执行的权限

    $指定行内数据列

    自动给一行中的每个数据元素分配一个变量 ,默认情况下:

    • $0代表整个文本行;
    • $1代表文本行中的第1个数据字段;
    • $2代表文本行中的第2个数据字段;
    • $n代表文本行中的第n个数据字段。

    文本行中,每个数据字段都是通过字段分隔符划分的,默认是空白字符(tab或空格),也可以通过-F指定分隔符

    echo "hello world"|awk '{ print $1}'
    hello
    echo "hello world"|awk '{ print $2}'
    world
    #指定0为分隔符
    echo "a0b0c0"|awk -F0 '{ print $3}'
    c
    

    =号赋值

    #将字符串d赋值给第三个字段
    echo "a0b0c0"|awk -F0 '{ $3="d";print $3}'
    d
    

    BEGIN和END

    cat begin1.txt
    line 1
    line 2
    line 3
    awk 'BEGIN {print "add new line in the beginning"}; { print $2 };END { print "end fo file"} ' begin1.txt
    add new line in the beginning
    1
    2
    3
    end fo file
    

    示例2

    cat beginscrpit.awk
    BEGIN {
            print "the latest of users and shells"
            print "User ID 	 Shell"
            print "--------	------"
            FS=":"
    };
    {
            print $1 "     	 " $7
    }
    END {
            print "the end of file"
    }
    awk -f beginscrpit.awk /etc/passwd
    the latest of users and shells
    User ID          Shell
    --------        ------
    root             /bin/bash
    daemon           /usr/sbin/nologin
    bin              /usr/sbin/nologin
    sys              /usr/sbin/nologin
    the end of file
    

    BEGIN在读取/etc/passwd文本行前打印开头行,并指定分隔符为:

    中间打印第1字段和第7个字段

    END读取完文本行后,执行

    内置变量

    变量 描述
    FIELDWIDTHS 由空格分隔的一列数字,定义了每个数据字段确切宽度
    FS 输入字段分隔符,默认是空格或tab
    RS 输入记录分隔符,默认是换行符
    OFS 输出字段分隔符
    ORS 输出记录分隔符
    echo '11:12:13-21:22:23-31:32:33-41:42:43'|awk 'BEGIN { FS=":";RS="-";OFS="~";ORS="&"};{print $1, $2}'
    11~12&21~22&31~32&41~42&
    

    默认情况下, gawk将RS和ORS设为换行符。默认的RS值表明,输入数据流中的每行新文本就是一条新纪录。

    print命令会自动将OFS变量的值放置在输出中的每个字段间。

    echo '123456789 '|awk 'BEGIN {FIELDWIDTHS="2 3 5" }{print $1,$2,$3}'
    12 345 6789
    

    一旦设置了FIELDWIDTH变量, gawk就会忽略FS变量,并根据提供的字段宽度来计算字段。

    数据变量

    变 量 描 述
    ARGC 当前命令行参数个数
    ARGIND 当前文件在ARGV中的位置
    ARGV 包含命令行参数的数组
    CONVFMT 数字的转换格式(参见printf语句),默认值为%.6 g
    ENVIRON 当前shell环境变量及其值组成的关联数组
    ERRNO 当读取或关闭输入文件发生错误时的系统错误号
    FILENAME 用作gawk输入数据的数据文件的文件名
    FNR 当前数据文件中的数据行数
    IGNORECASE 设成非零值时,忽略gawk命令中出现的字符串的字符大小写
    NF 数据文件中的字段总数
    NR 已处理的输入记录数
    OFMT 数字的输出格式,默认值为%.6 g
    RLENGTH 由match函数所匹配的子字符串的长度
    RSTART 由match函数所匹配的子字符串的起始位置
    gawk 'BEGIN{print ARGC,ARGV[1]}' data1
    2 data1
    gawk 'BEGIN{print ARGC,ARGV[0]}' data1
    2 gawk
    

    ARGC变量表明命令行上有两个参数。这包括gawk命令和data1参数(记住,程序脚本并不算参数)。

    gawk 'BEGIN{FS=":"; OFS=":"} {print $1,$NF}' /etc/passwd
    fly:/bin/bash
    sftpuser:/bin/sh
    gitlab-www:/bin/false
    git:/bin/sh
    

    NF变量含有数据文件中最后一个数据字段的数字值。可以在它前面加个美元符将其用作字段变量。 NF变量可以让你在不知道具体位置的情况下指定记录中的最后一个数据字段。

    gawk '
    > BEGIN {FS=","}
    > {print $1,"FNR="FNR,"NR="NR}
    > END{print "There were",NR,"records processed"}' data1 data1
    data11 FNR=1 NR=1
    data21 FNR=2 NR=2
    data31 FNR=3 NR=3
    data11 FNR=1 NR=4
    data21 FNR=2 NR=5
    data31 FNR=3 NR=6
    There were 6 records processed
    

    FNR变量的值在gawk处理第二个数据文件时被重置了,而NR变量则在处理第二个数据文件时继续计数。

    自定义变量

    awk 'BEGIN { testing="this is a test" ;print testing}'
    this is a test
    

    gawk自定义变量名可以是任意数目的字母、数字和下划线,但不能以数字开头。重要的是,变量名区分大小写。

    awk 'BEGIN { x=2;y=x*2+3 ;print y}'
    7
    

    gawk编程语言包含了用来处理数字值的标准算数操作符。其中包括求余符号( %)和幂运算符号( ^或**)。

    给脚本中的变量赋值

    cat begin1.txt
    line 1
    line 2
    line 3
    cat script
    {
     print $n
    }
    awk -f script n=1 begin1.txt
    line
    line
    line
    

    使用命令行参数来定义变量值会有一个问题。在你设置了变量后,这个值在代码的BEGIN部分不可用。

    可以用-v命令行参数来解决这个问题。它允许你在BEGIN代码之前设定变量。

    cat script2
    BEGIN{print "The starting value is",n; FS=","}
    {print $n}
    gawk -v n=3 -f script2 data1
    The starting value is 3
    data13
    data23
    data33
    

    正则匹配模式

    与sed的匹配模式大同小异,具体参考sed

     awk 'BEGIN{FS=":"} /git/{print $1}' /etc/passwd
    gitlab-www
    git
    

    在/etc/passwd文件中,匹配到git的行输出第一个字段

    匹配操作符~

    匹配操作符允许将正则表达式限定在记录中特定的数据字段

    cat data1
    data11,data12,data13,data14,data15
    data21,data22,data23,data24,data25
    data31,data32,data33,data34,data35
    gawk 'BEGIN{FS=","} $1~/data2/{print $0}' data1
    data21,data22,data23,data24,data25
    gawk 'BEGIN{FS=","} $1!~/data2/{print $0}' data1
    data11,data12,data13,data14,data15
    data31,data32,data33,data34,data35
    

    表示第一个字段匹配data2则打印整行文本

    !~表达没有匹配,则执行脚本

    数学表达式

    gawk -F: '$4==0{print $1}' /etc/passwd
    root
    ##也支持以下数学表达式
    x == y:值x等于y。
    x <= y:值x小于等于y。
    x < y:值x小于y。
    x >= y:值x大于等于y。
    x > y:值x大于y。
    

    参考 /etc/passwd中第四个字段为0的行,即显示所有属于root用户组(组ID为0)的系统用户

    结构化命令

    if、else

    cat numdata
    1
    2
    5
    10
    20
    30
    awk '{ if($1>5){ print $1 *2 }else {print $1} }' numdata
    1
    2
    5
    20
    40
    60
    

    while

    cat numdata2
    1 2 3
    4 5 6
    10 20 30
    gawk '{ total = 0;i = 1;while (i < 4){total += $i;i++;}print total;}' numdata2
    6
    15
    60
    

    for

    gawk '{ total = 0;for (i=1;i < 4;i++){total += $i;} print total}' numdata2
    6
    15
    60
    

    时间函数

    函数 描述
    mktime(datespec) 将一个按YYYY MM DD HH MM SS [DST]格式指定的日期转换成时间戳值
    strftime(format,[timestamp]) 格式化时间戳,参考linux date命令格式
    systime() 返回当前时间搓
    gawk 'BEGIN { print systime()}'
    1625014946
    gawk 'BEGIN { print strftime("%Y-%m-%d %H:%M:%S",systime())}'
    2021-06-30 09:13:51
    gawk 'BEGIN { print mktime("2020 06 21 11 21 24")}'
    1592709684
    

    字符串函数

    函数 描述
    asort(s [,d]) 按数组s的元素值排序,索引值会被替换为连续数字。如果指定d,则排序后存储在数组d中
    asorti(s [,d]) 将数组s按索引值排序。生成的数组会将索引值作为数据元素值。
    gensub(r, s, h [, t]) 查找$0或指定字符串t,匹配正则表达式r,如果h为‘g’或‘G’,则全局替换为字符串s,否则如果h为数字则替换为匹配到的第h个文本
    gsub(r, s [,t]) 查找变量$0或目标字符串t(如果提供了的话)来匹配正则表达式r。如果找到了,就全部替换成字符串
    index(s, t) 返回字符串t在字符串s中的索引值,如果没找到的话返回0
    length([s]) 返回字符串s的长度;如果没有指定的话,返回$0的长度
    match(s, r [,a]) 返回字符串s中正则表达式r出现位置的索引。如果指定了数组a,它会存储s中匹配正则表达式的那部分
    split(s, a [,r]) 将s用FS字符或正则表达式r(如果指定了的话)分开放到数组a中。返回字段的总数
    sprintf(format,variables) 用提供的format和variables返回一个类似于printf输出的字符串
    sub(r, s [,t]) 在变量$0或目标字符串t中查找正则表达式r的匹配。如果找到了,就用字符串s替换掉第一处匹配
    substr(s, i [,n]) 返回s中从索引值i开始的n个字符组成的子字符串。如果未提供n,则返回s剩下的部分
    tolower(s) 将s中的所有字符转换成小写
    toupper(s) s中的所有字符转换成大写
    #排序
    cat stringScript
    BEGIN {
            var["a"]=1
            var["g"]=5
            var["b"]=3
            var["c"]=12
            asort(var,test)
            for(i in test){
                    print "index:",i,"-value :",test[i]
            }
    }
    ##
    gawk -f stringScript
    index: 1 -value : 1
    index: 2 -value : 3
    index: 3 -value : 5
    index: 4 -value : 12
    #将asort修改为asorti
    gawk -f stringScript2
    index: 1 -value : a
    index: 2 -value : b
    index: 3 -value : c
    index: 4 -value : g
    
    #替换匹配,替换指定位置
    echo a b c a b c | gawk '{ print gensub(/a/, "AA", 2) }'
    a b c AA b c
    #替换匹配全局替换
    #\2 \1代表正则表达式中匹配到的第几个()
    cat stringScript3
    BEGIN {
            s = "abc def"
            print gensub(/(.+) (.+)/,"\2 \1","g",s)
    }
    
    #匹配返回索引
    gawk 'BEGIN{ print index("123456","23")}'
    2
    gawk 'BEGIN{ print index("123456","7")}'
    0
    gawk 'BEGIN{ print index("123456","1")}'
    1
    #长度
    gawk 'BEGIN{ print length("1234561")}'
    7
    #正则匹配返回索引
    gawk 'BEGIN{ print match("122123123",/23/)}'
    5
    #切分
    gawk 'BEGIN{
    > s="abcdefg"
    > FS="c"
    > split(s,a)
    > for(i in a){
    > print a[i]
    > }
    > }'
    ab
    defg
    #截取字符串
    gawk 'BEGIN{ print substr("122123123",5)}'
    23123
    

    自定义函数

    gawk '
    function> function printStrTwice(s){
    > print "s*s="
    > return s*s
    > }
    > BEGIN {
    > print printStrTwice(11)
    > }
    > '
    s*s=
    121
    

    function关键字 定义函数

    return语句返回值

    gawk函数库

    cat funclib
    function myprint()
    {
    	printf "%-16s - %s
    ", $1, $4
    }
    function myrand(limit)
    {
    	return int(limit * rand())
    }
    function printthird()
    {
    	print $3
    }
    
    cat script4
    BEGIN{ FS="
    "; RS=""}
    {
    	myprint()
    }
    #调用
    gawk -f funclib -f script4 data2
    
  • 相关阅读:
    word无法启动转换器RECOVR32.CNV
    win10致远OA显示正在转换。请稍等,不能获取office文件转换服务
    视频编辑剪辑软件
    软件质量属性——可修改性
    《架构之美》阅读笔记五
    架构漫谈一
    《架构之美》阅读笔记三
    《架构之美》阅读笔记二
    机器学习七讲——最优化
    机器学习六讲——降维
  • 原文地址:https://www.cnblogs.com/froggengo/p/14965337.html
Copyright © 2011-2022 走看看