zoukankan      html  css  js  c++  java
  • AWK

    awk提供了许多强大的字符串函数,见下表:
    awk内置字符串函数
    gsub(r,s)    在整个$0中用s替代r
    gsub(r,s,t)    在整个t中用s替代r
    index(s,t)    返回s中字符串t的第一位置
    length(s)    返回s长度
    match(s,r)    测试s是否包含匹配r的字符串
    split(s,a,fs)    在fs上将s分成序列a
    sprint(fmt,exp)    返回经fmt格式化后的exp
    sub(r,s)    用$0中最左边最长的子串代替s
    substr(s,p)    返回字符串s中从p开始的后缀部分
    substr(s,p,n)    返回字符串s中从p开始长度为n的后缀部分 详细说明一下各个函数的使用方法。

    gsub函数有点类似于sed查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以正则表达式的形式执行。第一个函数作用于记录$0,第二 个gsub函数允许指定目标,然而,如果未指定目标,缺省为$0。
    index(s,t)函数返回目标字符串s中查询字符串t的首位置。length函数返回字符串s字符长度。match函数测试字符串s是否包含一个正则表达式r定义的匹配。split使用域分隔符fs将字符串s划分为指定序列a。sprint函数类似于printf函数(以后涉及),返回基本输出格式fmt的结果字符串exp。sub(r,s)函数将用s替代$0中最左边最长的子串,该子串被(r)匹配。sub(s,p)返回字符串s在位置p后的后缀。substr(s,p,n)同上,并指定子串长度为n。
    现在看一看awk中这些字符串函数的功能。

    1.gsub
    要在整个记录中替换一个字符串为另一个,使用正则表达式格式,/目标模式/,替换模式/。例如改变学生序号4842到4899:

    $ awk 'gsub(/4842/, “4899”) {print $0}' grade.txt
    J.Troll 07/99 4899 Brown-3 12 26 26

    echo "i am hifdafafdst"|awk '{gsub(/am/,"abcc",$0);print $0}'
    i abcc hifdafafdst

    2.index
    查询字符串s中t出现的第一位置。必须用双引号将字符串括起来。例如返回目标字符串Bunny中ny出现的第一位置,即字符个数。

    $ awk 'BEGIN {print index("Bunny", "ny")} grade.txt
    4

    3.length
    返回所需字符串长度,例如检验字符串J.Troll返回名字及其长度,即人名构成的字符个数。

    $ awk '$1=="J.Troll" {print length($1) " "$1}' grade.txt
    7 J.Troll

    还有一种方法,这里字符串加双引号。

    $ awk 'BEGIN {print length("A FEW GOOD MEN")}'
    14

    4.match
    match测试目标字符串是否包含查找字符的一部分。可以对查找部分使用正则表达式,返回值为成功出现的字符排列数。如果未找到,返回0,第一个例子在ANCD中查找d。因其不存在,所以返回0。第二个例子在ANCD中查找D。因其存在,所以返回ANCD中D出现的首位置字符数。第三个例子在学生J.Lulu中查找u。

    $ awk '{BEGIN {print match("ANCD", /d/)}'
    0
    $ awk '{BEGIN {print match("ANCD", /C/)}'
    3
    $ awk '$1=="J.Lulu" {print match($1, "u")} grade.txt
    4

    5.split
    使用split返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔符-,例如AD2-KP9-JU2-LP-1,将之划分成一个数组。使用split,指定分隔符及数组名。此例中,命令格式为("AD2-KP9-JU2-LP-1",parts_array,"-"),split然后返回数组下标数,这里结果为4。还有一个例子使用不同的分隔符。

    $ awk '{BEGIN {print split("123#456#678", myarray, "#")}'
    3

    这个例子中,split返回数组myarray的下标数。数组myarray取值如下:

    Myarray[1]="123"
    Myarray[2]="456"
    Myarray[3]="789"

    6.sub
    使用sub发现并替换模式的第一次出现位置。字符串STR包含‘popedpopopill’,执行下列sub命令sub(/op/,"op",STR)。模式op第一次出现时,进行替换操作,返回结果如下:
    ‘pOPedpopepill’。
    假如grade.txt文件中,学生J.Troll的记录有两个值一样,“目前级别分”与“最高级别分”。只改变第一个为29,第二个仍为24不动,操作命令为sub(/26/,"29",$0),只替换第一个出现24的位置。

    $ awk '$1=="J.Troll" sub(/26/, "29", $0)' grade.txt
    L.Troll 07/99 4842 Brown-3 12 29 26
    L.Transley 05/99 4712 Brown-2 12 30 28

    7.substr
    substr是一个很有用的函数。它按照起始位置及长度返回字符串的一部分。例子如下:

    $ awk '$1=="L.Transley" {print substr($1, 1,5)}' grade.txt
    L.Tan
    上面例子中,指定在域1的第一个字符开始,返回其前面5个字符。
    如果给定长度值远大于字符串长度, awk将从起始位置返回所有字符,要抽取L.Tansley的姓,只需从第3个字符开始返回长度为7。可以输入长度99,awk返回结果相同。

    $ awk '{$1=="L.Transley" {print substr($1, 3,99)}' grade.txt
    Transley

    substr的另一种形式是返回字符串后缀或指定位置后面字符。这里需要给出指定字符串及其返回字串的起始位置。例如,从文本文件中抽取姓氏,需操作域 1,并从第三个字符开始:

    $ awk '{print substr($1, 3)}' grade.txt
    Troll
    Transley

    还有一个例子,在BEGIN部分定义字符串,在END部分返回从第t个字符开始抽取的子串。

    $ awk '{BEGIN STR="A FEW GOOD MEN"} END {print substr(STR,7)) grade.txt
    GOOD MEN

    8.从shell中向awk传入字符串 
    awk脚本大多只有一行,其中很少是字符串表示的,这一点通过将变量传入awk命令行会变得很容易。现就其基本原理讲述一些例子。
    使用管道将字符串stand-by传入awk,返回其长度。

    $ echo "Stand-by" | awk '{print length($0)}'
    8

    设置文件名为一变量,管道输出到awk,返回不带扩展名的文件名。

    $ STR="mydoc.txt"
    $ echo $STR | awk '{print subst($STR, 1, 5)}'
    mydoc

    设置文件名为一变量,管道输出到awk,只返回其扩展名。
    $ STR="mydoc.txt"
    $ echo $STR | awk '{print substr($STR, 7)}'
    txt

    1.print函数  
    例子1:  
    $ date  
    2005年04月30日 星期六 19时29分25秒 CST  
    $ date|awk '{print "Date:" $1 " Time:" $3}'  
    Date:2005年04月30日  
    Time:19时34分24秒  
    注意,用date命令查看时间格式。不同的语言可能格式也不一样,因此 awk也要随之而变 是转义序列,表示换行符。常见转义序列如下表:  转义序列用一个反斜杠后跟一个字母或者数字表示
    转义序列
    含义
    
    退格
    f
    换页

    换行

    制表符(空格)

    回车
    例子2:  
    $ awk '/Sally/{print " Have a nice day, "$1,$2 "!"}' employees  
    Have a nice day, Sally Chang!  
    解释:如果包含模式Sally,则print函数打印两个跳格,串Have a nice day,第一个字段和第二个字段,然后跟叹号。  
    2.  在一个文件里的awk命令  
    如果awk命令放在文件里,就使用-f选项和awk文件名结合使用。处理过程: 把一条记录读到awk的缓存里而且对该记录测试并执行awk文件里的每个命令。在awk完成对第一记录的操作后,删除该记录并把下一条记录读入缓存,依此类推。如果操作不受模式控制,则默认行为是打印整个记录。  
    例子:  
    $ cat employees  
    Tom Jones 4424 5/12/66 543354  
    Mary Adams 5346 11/4/63 28765  
    Sally Chang 1654 7/22/54 650000  
    Billy Black 1683 9/23/44 336500  
    $ cat awkfile  
    /^Mary/{print "Hello Mary!"}  
    {print $1, $2, $3}  
    $ awk -f awkfile employees  
    Tom Jones 4424  
    Hello Mary!  
    Mary Adams 5346  
    Sally Chang 1654  
    Billy Black 1683  
    3. 记录和字段  
    1〉记录:awk不把输入数据看作一个无穷的字符串,而是把它看作一种格式 或结构。默认情况下把每行叫做一个记录(record),并以一个换行符终 止。输入和输出的记录分隔符默是回车符,保存在内置awk变量ORS 和RS中。ORS和RS可以改变,但是方式有限。  
    例子:  
    $ awk '{print $0}' employees  
    Tom Jones 4424 5/12/66 543354  
    Mary Adams 5346 11/4/63 28765  
    Sally Chang 1654 7/22/54 650000  
    Billy Black 1683 9/23/44 336500  
    解释:变量$0保存当前记录,这条命令相当于awk '{print}' employees  
    例子:  
    $ awk '{print NR,$0}' employees  
    1 Tom Jones 4424 5/12/66 543354  
    2 Mary Adams 5346 11/4/63 28765  
    3 Sally Chang 1654 7/22/54 650000  
    4 Billy Black 1683 9/23/44 336500  
    解释:NR代表行号。  
    4字段  
    类似表中的字段,是指记录中的一个词条。默认字段分隔符是空白区字段, 也就是空格或制表符(TAB)。Awk中用NF来记录每条记录的字段数量。  
    字段分隔符  
    输入字段分隔符:awk的内置变量FS保存输入字段分隔符的值。当时用FS 的默认值时,awk用空格或制表符分隔字段,删除前导空白区和制表符。FS 可以改变,可以在BEGIN语句中改变,也可以在命令中改变。要想在命 令中改变需要用-F选项。  
    举例:  
    $ cat employees2  
    Tom Jones:4424:5/12/66:543354  
    Mary Adams:5346:11/4/63:28765  
    Sally Chang:1654:7/22/54:650000  
    Billy Black:1683:9/23/44:336500  
    $ awk '{print $1,$2}' employees2  
    Tom Jones:4424:5/12/66:543354  
    Mary Adams:5346:11/4/63:28765  
    Sally Chang:1654:7/22/54:650000  
    Billy Black:1683:9/23/44:336500  
    $ awk -F: '{print $1,$2}' employees2  
    Tom Jones 4424  
    Mary Adams 5346  
    Sally Chang 1654  
    Billy Black 1683  
    举例2:多个字段分隔符。如果使用多个字段分隔符,要将其封装在方括号里。  
    $ awk -F'[ : ]' '{print $1,$2,$3}' employees2  
    Tom Jones 4424  
    Mary Adams 5346  
    Sally Chang 1654  
    Billy Black 1683  
    解释:把空格、制表符、冒号当成输入字段分隔符。
    输出字段分隔符:默认的输出字段分隔符用逗号来分隔,被分隔的字段之间打 印一个空格,如果字段之间没有逗号,则打印时各字段将挤在一起。  
    5.模式和操作  
    awk 模式(patterns)控制awk将对一行输入作什么样的操作。一个模式包括 一个正则表达式,一个产生正确或者错误条件的表达式,或者它们的组合。 默认操作时打印模式中符合表达式条件的各行。当读入一个模式时,有一条 隐含的if语句。如果if语句是隐含的,周围可以没有花括号。  
    例子:  
    $ awk '$37/22/54 650000  
    Billy Black 1683 9/23/44 336500  
    解释:如果第3个字段小于4000,则打印该字段。  
    操作:操作(actions)是封装在花括号里且由分号分隔的语句。如果一个模式 在一个操作之前,则该模式规定了何时执行该操作。  
    举例:  
    $ awk '/Tom/{print "Hello there," $1}' employees  
    Hello there,Tom  
    解释:如果记录中包含Tom,则打印Hello there,Tom  
    6.正则表达式  
    一个正则表达式对awk来说是一个由封装在正斜杠里的字符组成的模式。Awk 支持的正则表达式与egrep基本一样,可以参考下表
    元字符
    说明
    ^
    字符串首
    $
    字符串尾
    .
    单个任意字符
    *
    零个或者多个前导字符
    +
    一个或者多个前导字符
    ?
    零个或者一个前导字符
    [ABC]
    匹配【】中的任一字符
    [^ABC]
    匹配任何一个不在【】中的字符
    [A-Z]
    匹配A-Z之间的任一字符
    A|B
    A或者B
    (AB)+
    一个或者多个AB组合
    *
    *本身
    &
    替代符,替代查找串中匹配的内容
    举例:  
    $ awk '/^Mary/' employees  
    Mary Adams 5346 11/4/63 28765  
    解释:显示employees文件中以Mary开头的行  
    $ awk '/^[A-Z][a-z]* /' employees  
    Tom Jones 4424 5/12/66 543354  
    Mary Adams 5346 11/4/63 28765  
    Sally Chang 1654 7/22/54 650000  
    Billy Black 1683 9/23/44 336500  
    解释:显示行开头是一个大写字母,然后跟一个或多个小写字母,再跟一个
    空格。  
    匹配操作符(~)、否定号(!)用来与以条记录或字段里的表达式相匹配。  
    例子:  
    $ awk '$1 ~/[Bb]ill/' employees  
    Billy Black 1683 9/23/44 336500  
    解释:awk将显示第一个字段里与Bill或者bill相匹配的行  
    $ awk '$1 !~/ly$/' employees  
    Tom Jones 4424 5/12/66 543354  
    Mary Adams 5346 11/4/63 28765  
    解释:显示第一个字段中末尾不是ly的所有行。  
    比较表达式比较行,如果行里的条件为真,就执行操作。如果给表达式求值 为真则值等于1,反之等于0。  
    7.关系操作符  
    下表列出了关系操作符。  
    运算符
    含义
    示例

    小于
    x
    小于等于
    x
    ==
    等于
    x==y
    !=
    不等于
    x!=y
    >=
    大于等于
    x>=y
    >
    大于
    x>y
    ~
    与正则表达式匹配
    X~/y/
    !~
    不与正则表达式匹配
    x!~/y/
    关系操作符举例:  
    $ cat employees  
    Tom Jones 4423 5/12/66 543354  
    Mary Adams 5346 11/4/63 28765  
    Sally Chang 1654 7/22/54 650000  
    Billy Black 1683 9/23/44 336500  
    $ awk '$3==4423' employees  
    Tom Jones 4423 5/12/66 543354  
    $ awk '$3 >;5000{print $1}' employees  
    Mary  
    $ awk '$2 !~/Adam/' employees  
    Tom Jones 4423 5/12/66 543354  
    Sally Chang 1654 7/22/54 650000  
    Billy Black 1683 9/23/44 336500  
    条件表达式:一个条件表达式用两个符号,问号和冒号来给表达式求值。  
    8.条件表达式  
    格式:  
    conditional expression1?expression2:expression3  它等同于
    {if(expression1)  
    expression2  
    else  
    expression3  
    }  
    条件表达式举例:  
    awk '{max=($1>;$2)?$1:$2;print max}' employees 
    解释:如果第一个字段大于第二个字段,就把第一个字段的内容赋给max,反之把第
    二个字段的内容赋给max,然后打印max  
    9.计算  
    可以在模式里执行计算。awk以浮点方式执行所有的算术运算。
    +  加  
    -  减  
    * 乘  
    / 除  
    10.复合模式  
    复合模式 (compound patterns) 是把模式和逻辑操作符相结合的表达式,给 一个表达式从左到右求值。  
                                  逻辑运算符
    运算符
    含义
    例子
    &&
    逻辑与
    A&&B
    ||
    逻辑或
    A||B
    !
    逻辑非
    !A
    复合模式举例:  
    $ awk '$3>;4000 && $35/12/66 543354  
    Mary Adams 5346 11/4/63 28765  
    $ awk '!($3>;4000 && $311.范围模式  
    范围模式从一个模式的第一次出现匹配到第二个模式的第一次出现,然后从 第一个模式的第二次出现匹配到第二个模式的第二次出现等等。如果第一个 模式被匹配,而第二个模式没有找到,则awk将显示直到末尾的所有行。  
    例子:  
    $ cat datafile  
    northwest NW Joel Craig 3.0 .98 3 4  
    western WE Sharon Kelly 5.3 .97 5 23  
    southwest SW Chris Foster 2.7 .8 2 18  
    southern SO May Chin 5.1 .95 4 15  
    southeast SE Derek Johnson 4.0 .7 4 17  
    eastern EA Susan Beal 4.4 .84 5 20  
    northeast NE TJ Nichols 5.1 .94 3 13  
    north NO Val Shultz 4.5 .89 5 9  
    central CT Sheri Watson 5.7 .94 5 13  
    $ awk '/^north/,/^west/' datafile  
    northwest NW Joel Craig 3.0 .98 3 4  
    western WE Sharon Kelly 5.3 .97 5 23  
    northeast NE TJ Nichols 5.1 .94 3 13  
    north NO Val Shultz 4.5 .89 5 9  
    central CT Sheri Watson 5.7 .94 5 13  
    12.变量  
    内置变量要大写,他们可以用在表达式里而且可以被重置。如下表  
    变量名
    含义
    ARGC
    命令行参数的数目
    FILENAME
    当前输入文件的的文件名
    FNR
    当前文件的记录数
    FS
    输入字段分隔符,默认为空格
    NF
    当前记录中的字段数
    NR
    目前的记录数
    OFS
    输出字段分隔符
    ORS
    输出记录分隔符
    RS
    输入记录分隔符
    IGNORECASE
    在正则表达式和字符串匹配中不区分大小写(值为非0时)
    内置变量举例:  
    $ awk -F: '$1=="Mary Adams"{print NR,$1,$2,$NF}' employees2  
    2 Mary Adams 5346 28765  
    解释:-F选项把分隔符改成冒号。如果字段1等于Mary Adams,则打印记 录号、第一个字段、第二个字段和最后一个字段($NF)  
    赋值运算符
    运算符
    含义
    等效表达式
    =
    A=5
    A=5
    +=
    A=a+5
    A+=5
    -=
    A=a-5
    a-=5
    *=
    A=a*5
    A*=5
    /=
    A=a/5
    a/=5

     

  • 相关阅读:
    ZOJ 2158 Truck History
    Knight Moves (zoj 1091 poj2243)BFS
    poj 1270 Following Orders
    poj 2935 Basic Wall Maze (BFS)
    Holedox Moving (zoj 1361 poj 1324)bfs
    ZOJ 1083 Frame Stacking
    zoj 2193 Window Pains
    hdu1412{A} + {B}
    hdu2031进制转换
    openjudge最长单词
  • 原文地址:https://www.cnblogs.com/xieqianli/p/4219557.html
Copyright © 2011-2022 走看看