zoukankan      html  css  js  c++  java
  • linux之awk命令详解

    AWK是一种优良的文本处理工具。它不仅是 Linux 中也是任何环境中现有的功能最强大的数据处理引擎之一。


    AWK 提供了极其强大的功能:可以进行样式装入、流控制、数学运算符、进程控制语句甚至于内置的变量和函数。
    它具备了一个完整的语言所应具有的几乎所有精美特性。实际上 AWK 的确拥有自己的语言:AWK 程序设计语言,
    它允许您创建简短的程序,这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表,还有无数其他的功能。
    最简单地说, AWK 是一种用于处理文本的编程语言工具。AWK 在很多方面类似于 shell 编程语言,

    尽管操作可能会很复杂,但命令的语法始终是:
    awk '{pattern + action}' 或者 awk 'pattern {action}'

    其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。

    awk提供了一个完整的编程模型。

    awk程序由一个主输入循环维持。并且反复执行。直到终止条件被触发。

    但是这些处理都是由awk自己完成的。我们只需要编写循环中的处理。

    会循环的处理pattern匹配的每一条数据,直到处理完毕。

    awk中还定义了两个特殊的字段。BEGIN和END。BEGIN用于在主输入循环之前执行。即在未读取输入文件之前执行。END则相反,

    用于在主输入循环之后执行。即在读取输入文件执行完毕后执行。

    awk的调用方法也分为三种:

    ①awk [-F 域分隔符] 'awk程序段' 输入文件

    ②awk -f awk脚本文件 输入文件

    ③./awk脚本文件 输入文件(awk脚本需要以'#!'开头加上awk的路径,并且设置为可执行)

    可以看到,第一种方式中,可以通过-F来指定域分隔符。那这是什么意思呢?

    在awk中认为输入文件是结构化的,awk将每个输入文件行定义为记录。行中的每个字符串定义为域,域之间用空格,tab键或其他字符进行分割,分割的符号叫做分隔符。多个连续的空格或tab键被当作一个分隔符来处理。

    在awk中定义了一个域操作符$来指定执行动作的域。域操作符后面跟数字或变量来标识域的位置。域的编号从1开始,0表示所有的域。

    比如:zhangsan   男   24    江西  138xxxxxxxx

    上面这条记录中,$0就代表了整条记录,$1就代表[zhangsan],$2就代表[男]。

    尽管-F可以改变分隔符,但是在awk中还提供了一种更方便的方式来改变分隔符。就是awk环境变量FS。

    我们可以通过在BEGIN字段中设置FS的值来改变分隔符。

    下面就来简单体验下awk的简单使用:

    [fuwh@localhost 12:42 ~/stu]$ cat tx
    fuwh men:jiangxi
    zhangsan girl:shanghai
    [fuwh@localhost 12:45 ~/stu]$ awk '{print $2}' tx
    men:jiangxi
    girl:shanghai
    [fuwh@localhost 12:46 ~/stu]$ awk -F":" '{print $2}' tx
    jiangxi
    shanghai
    [fuwh@localhost 12:47 ~/stu]$ awk 'BEGIN {FS=":"} {print $1}' tx
    fuwh men
    zhangsan girl
    [fuwh@localhost 12:48 ~/stu]$

    awk既然也是一种编程语言,那里面肯定也是有很多普通语言所具有的运算符,循环,判断之类的。

    在awk中awk程序段都是由模式和动作组成的。模式是一组用于测试输入行是否需要执行动作的规则,动作包含语句,函数和表达式的执行过程,在模式匹配中,经常需要用到正则表达式。awk支持'?'和'+'这两个元字符。

    关系和布尔运算符

    关系运算符主要用于awk模式匹配

    <:小于

    >:大于

    <=:小于或等于

    >=:大于或等于

    ==:等于

    !=:不等于

    ~:匹配正则表达式

    !~:不匹配正则表达式

    布尔运算:

    ||:逻辑或

    &&:逻辑与

    !:逻辑非

    例子

    [fuwh@localhost 13:31 ~/stu]$ cat tx
    fuwh:men:jiangxi
    zhangsan:girl:shanghai
    lisi:girl:beijing
    wangwu:feman:shenzhen
    [fuwh@localhost 13:31 ~/stu]$ awk 'BEGIN{FS=":"} {if($2=="men"||$2~/girl/) print $3}' tx
    jiangxi
    shanghai
    beijing
    [fuwh@localhost 13:34 ~/stu]$

    表达式

    在awk中也可以定义变量,一个表达式可以包含赋值,运算符等等。

    +:加

    -:减

    *:乘

    /:除

    %:模

    ^或**:乘方

    ++x:自增,在返回x之前

    x++:自增,在返回x之后

    例子:

    [fuwh@localhost 14:06 ~/stu]$ cat tx
    fuwh:men:jiangxi
    zhangsan:girl:shanghai
    lisi:girl:beijing
    wangwu:feman:shenzhen
    [fuwh@localhost 14:10 ~/stu]$ awk 'BEGIN{FS=":"} {if($2=="girl") x++} END{print "女生个数:" x}' tx
    女生个数:2
    [fuwh@localhost 14:10 ~/stu]$

    系统变量

    在awk中,还内建了许多变量,用来设置环境信息 。叫做系统变量。

    系统变量分为两种:一种是用于改变awk的默认值,如域分隔符FS,第二种用于定义系统值。在处理文本的时候可以读取这些系统值,如记录中的域数量,当前记录数,当前文件名之类的。

    下面是一些常见的环境变量及其意义:

    $n:当前记录的第n个域,域间由FS分割
    $0:记录所有的域

    ARGC:命令行参数的数量

    ARGIND:命令行中当前文件的位置(以0开始标号)

    ARGV:命令行参数的数组

    CONVFMT:数字转换格式

    ENVIRON:环境变量关联数组

    ERRNO:最后一个系统错误的描述

    FIELDWIDTHS:字段宽度列表,以空格键分割

    FILENAME:当前文件名

    FNR:浏览文件的记录数

    FS:字段分隔符,默认是空格键

    IGNORECASE:布尔变量,如果威震,则进行忽略大小写的匹配

    NF:当前记录中的域数量

    NR:当前记录数

    OFMT:数字的输出格式

    OFS:输出域分隔符,默认是空格键

    ORS:输出记录分隔符,默认是换行符

    RLENGTH:由match函数所匹配的字符串长度

    RS:记录分隔符默认是空格键

    RSTART:由match函数所匹配的字符串的第一个位置

    SUBSEP:数组下标分隔符,默认是34

    例子:

    [fuwh@localhost 14:31 ~/stu]$ cat tx
    fuwh:men:jiangxi
    zhangsan:girl:shanghai
    lisi:girl:beijing
    wangwu:feman:shenzhen
    [fuwh@localhost 14:31 ~/stu]$ awk 'BEGIN{FS=":"} {print "第"NR"条记录"} END{print FILENAME "共"FNR"条记录,每条有"NR"个域"}' tx
    第1条记录
    第2条记录
    第3条记录
    第4条记录
    tx共4条记录,每条有4个域
    [fuwh@localhost 14:32 ~/stu]$

    格式化输出

    前面我们都是用print进行输出,但是,在awk中,还提供了printf这个输出来进行格式化的输出工作。

    基本语法:

    printf (格式控制符,参数)

    printf的语句分为两部分,第一部分是格式控制符,都以%开始,用以描述格式规范,第二部分是参数列表,比如变量名列表。与格式控制符相对应。

    格式控制符又可以分为修饰符和格式符两种。

    修饰符:

    -:左对齐

    width:域的步长

    -prec:小数点右边的位数

    格式符:

    %c:ASCII字符

    %d:整型数

    %e:浮点数,科学计数法

    %f:浮点数

    %o:八进制数

    %s:字符串

    %x:十六进制数

    例子:

    [fuwh@localhost 14:35 ~/stu]$ cat tx
    fuwh:men:jiangxi
    zhangsan:girl:shanghai
    lisi:girl:beijing
    wangwu:feman:shenzhen
    [fuwh@localhost 14:46 ~/stu]$ awk 'BEGIN{FS=":"}{printf("%s	%s人
    ",$1,$3) }' tx
    fuwh    jiangxi人
    zhangsan        shanghai人
    lisi    beijing人
    wangwu  shenzhen人
    [fuwh@localhost 14:47 ~/stu]$

    内置字符串函数

    在awk中提供了强大的内置字符串函数,用于实现文本的字符串替换、查找以及分割等功能。

    gsub(r,s):在输入文件中用s替换r

    gsub(r,s,t):在t中用s替换r

    index(s,t):返回s中字符串第一个t的位置

    length(s):返回s的长度

    match(s,t):测试s是否包含匹配t的字符串

    split(s,t):在t上将r分成序列s

    sub(r,s,t):将t中第一次出现的r替换成s

    substr(r,s):返回字符串r中从s开始的后缀部分

    例子:

    [fuwh@localhost 14:59 ~/stu]$ cat tx
    fuwh:men:jiangxi
    zhangsan:girl:shanghai
    lisi:girl:beijing
    wangwu:feman:shenzhen
    [fuwh@localhost 15:03 ~/stu]$ awk 'BEGIN{FS=":"}{if($1=="fuwh") print(length($3))}' tx
    7
    [fuwh@localhost 15:04 ~/stu]$

    向awk脚本传递参数

    在awk中使用的变量,可以在命令行中进行赋值。实现向awk脚本传递参数。变量复制放在脚本之后、输入文件之前,格式为:

    awk 脚本 parameter=value 输入文件

     例子:

    [fuwh@localhost 15:26 ~/stu]$ ll tx*
    -rw-rw-r--. 1 fuwh fuwh 80 8月  14 13:31 tx
    -rwxrw-r--. 1 fuwh fuwh 41 8月  14 15:26 tx.awk
    [fuwh@localhost 15:26 ~/stu]$ cat tx tx.awk
    fuwh:men:jiangxi
    zhangsan:girl:shanghai
    lisi:girl:beijing
    wangwu:feman:shenzhen
    #!/bin/awk -f
    {printf("%s	%s
    ",$1,$3)}
    [fuwh@localhost 15:26 ~/stu]$ ./tx.awk FS=":" tx
    fuwh    jiangxi
    zhangsan        shanghai
    lisi    beijing
    wangwu  shenzhen
    [fuwh@localhost 15:26 ~/stu]$

    条件语句和循环语句

     awk中支持下面几种条件语句和循环语句。

    if(条件表达式)

      动作1

    [else

      动作2]

     while(条件表达式)

      动作

    do

      动作

    while(条件表达式)

    for(计数器初始值;测试计数器条件;计数器变化)

      动作

    数组

    数组的索引可以是数字,也可以是字符串,索引并不表示存储的顺序信息。在awk中,会自动维护一对索引和值的信息。

    awk中访问数组的所有元素:

    for(变量 in 数组名)

      xxxxx

    还可以使用in来判断是否在数组中存在

      索引名 in 数组名

    如果存在,则返回1,不存在则返回0

  • 相关阅读:
    EntityFramework
    在项目中整合log4net日志模块
    java Socket编程
    java动态代理
    多项式计算的Horner法则(秦九韶法则)
    1.6打印字符串排列
    1.5 输出整数N的二进制1的个数(递归)
    1.3输出任意实数
    Java super关键字调用父类的方法疑惑
    vs2010配置MPI
  • 原文地址:https://www.cnblogs.com/zerotomax/p/7356470.html
Copyright © 2011-2022 走看看