• Linux-(awk)


    它会依次读取文件的每一行内容, 然后对其进行处理,awk 命令默认从 stdio 标准输入获取文件内容, awk 使用一对单引号来表示 一些可执行的脚本代码,在可执行脚本代码里面,使用一对花括号来表示一段可执行代码块,可以同时存在多个代码块。 awk 的每个花括号内同时又可以有多个指令,每一个指令用分号分隔,awk 其实就是一个脚本编程语言。

    awk 命令的基本格式

    awk [options] 'program' file

    options 这个表示一些可选的参数选项

    program 这个表示 awk 的可执行脚本代码,这个是必须要有的。 

    file 这个表示 awk 需要处理的文件,注意是纯文本文件。

    先来一个 awk 的使用例子热热身 

    $ awk '{print $0}' /etc/passwd

    awk 命令的可执行脚本代码使用单引号括起来,紧接着里面是一对花括号,然后花括号里面就是一些可执行的脚本代码段。

    当 awk 每读取一行之后,它会依次执行双引号里面的每个脚本代码段。

    在上面这个例子中, $0 表示当前行。当你执行了上面的命令之后,它会依次将 /etc/passwd 文件的每一行内容打印输出。

    awk 自定义分隔符

    awk 默认的分割符为空格制表符,我们可以使用 -F 参数来指定分隔符

    $ awk -F ':' '{print $1}' /etc/passwd
    root
    bin

    上面的命令将 /etc/passwd 文件中的每一行用冒号 : 分割成多个字段,然后用 print 将第 1 列字段的内容打印输出

    如何在 awk 中同时指定多个分隔符

    比如现在有这样一个文件 some.log 文件内容如下:

    Grape(100g)1980
    raisins(500g)1990
    plum(240g)1997
    apricot(180g)2005
    nectarine(200g)2008

    现在我们想将上面的 some.log 文件中按照 "水果名称(重量)年份" 来进行分割:

    $ awk -F '[()]' '{print $1, $2, $3}' some.log
    Grape 100g 1980
    raisins 500g 1990
    plum 240g 1997
    apricot 180g 2005
    nectarine 200g 2008

    在 -F 参数中使用一对方括号来指定多个分隔符,awk 处理 some.log 文件时就会使用 "(" 和 ")" 来对文件的每一行进行分割。

    awk 内置变量的使用

    $0 这个表示文本处理时的当前行
    $1 表示文本行被分隔后的第 1 个字段列
    $2 表示文本行被分割后的第 2 个字段列
    $3 表示文本行被分割后的第 3 个字段列
    $n 表示文本行被分割后的第 n 个字段列
    NR 表示文件中的行号,表示当前是第几行
    NF 表示文件中的当前行列的个数,类似于 mysql 数据表里面每一条记录有多少个字段
    FS 表示 awk 的输入分隔符,默认分隔符为空格和制表符,你可以对其进行自定义设置
    OFS 表示 awk 的输出分隔符,默认为空格,你也可以对其进行自定义设置
    FILENAME 表示当前文件的文件名称,如果同时处理多个文件,它也表示当前文件名称

    比如我们有这么一个文本文件 fruit.txt 内容如下,我将用它来向你演示如何使用 awk 命令工具:

    peach    100   Mar  1997   China
    Lemon    150   Jan  1986   America
    Pear     240   Mar  1990   Janpan
    avocado  120   Feb  2008   china

    我们来瞧一瞧下面这些例子:

    打印输出文件的每一行的第 1 列、第 2 列和第 3 列内容
    $ awk '{print $1, $2, $3}' fruit.txt
    peach 100 Mar
    Lemon 150 Jan
    Pear 240 Mar
    avocado 120 Feb
    其中加入的逗号表示插入输出分隔符,也就是默认的空格
    
    通过对 $2 变量进行重新赋值,来隐藏每一行的第 2 列内容,并且用星号 * 来代替其输出
    $ awk '{$2 = "***"; print $0}' fruit.txt
    peach *** Mar 1997 China
    Lemon *** Jan 1986 America
    Pear *** Mar 1990 Janpan
    avocado *** Feb 2008 china
    
    在 print的参数列表中加入一些字符串或者转义字符之类的东东,让输出的内容格式更漂亮,但一定要记住要使用双引号。
    $ awk '{print $1 "	" $2 "	" $3}' fruit.txt
    peach   100     Mar
    Lemon   150     Jan
    Pear    240     Mar
    avocado 120     Feb
    
    awk 内置 NR 变量表示每一行的行号
    $ awk '{print NR "	" $0}' fruit.txt
    1   peach    100   Mar  1997   China
    2   Lemon    150   Jan  1986   America
    3   Pear     240   Mar  1990   Janpan
    4   avocado  120   Feb  2008   china
    
    awk 内置 NF 变量表示每一行的列数
    $ awk '{print NF "	" $0}' fruit.txt
    5   peach    100   Mar  1997   China
    5   Lemon    150   Jan  1986   America
    5   Pear     240   Mar  1990   Janpan
    5   avocado  120   Feb  2008   china
    
    
    $NF 就表示每一行的最后一列,因为 NF 表示一行的总列数,在这个文件里表示有 5 列,然后在其前面加上 $ 符号,就变成了 $5 ,表示第 5 列
    $ awk '{print $NF}' fruit.txt
    China
    America
    Janpan
    china
    $(NF-1) 表示倒数第 2 列, $(NF-2) 表示倒数第 3 列,依次类推。
    $ awk '{print $(NF - 1)}' fruit.txt
    1997
    1986
    1990
    2008

    多一个新文件叫 company.txt 内容如下:

    yahoo   100 4500
    google  150 7500
    apple   180 8000
    twitter 120 5000

    用 fruit.txt 和 company.txt 两个文件来向你演示 awk 同时处理多个文件的时候有什么效果

    $ awk '{print FILENAME "	" $0}' fruit.txt company.txt
    fruit.txt       peach    100   Mar  1997   China
    fruit.txt       Lemon    150   Jan  1986   America
    fruit.txt       Pear     240   Mar  1990   Janpan
    fruit.txt       avocado  120   Feb  2008   china
    company.txt     yahoo   100 4500
    company.txt     google  150 7500
    company.txt     apple   180 8000
    company.txt     twitter 120 5000

    当你使用 awk 同时处理多个文件的时候,它会将多个文件合并处理,变量 FILENAME 就表示当前文本行所在的文件名称。

    BEGIN 关键字的使用

    在脚本代码段前面使用 BEGIN 关键字时,它会在开始读取一个文件之前,运行一次 BEGIN 关键字后面的脚本代码段, BEGIN 后面的脚本代码段只会执行一次,执行完之后 awk 程序就会退出。

    $ awk 'BEGIN {print "Start read file"}' /etc/passwd
    Start read file

    awk 脚本中可以用多个花括号来执行多个脚本代码,就像下面这样:

    $ awk 'BEGIN {print "Start read file"} {print $0}' /etc/passwd
    Start read file
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin

    END 关键字使用方法

    awk 的 END 指令和 BEGIN 恰好相反,在 awk 读取并且处理完文件的所有内容行之后,才会执行 END 后面的脚本代码段。

    $ awk 'BEGIN {print "Start read file"} {print $0} END {print "End file"}' /etc/passwd
    Start read file
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    End file

    在 awk 中使用变量

    可以在 awk 脚本中声明和使用变量 

    $ awk '{msg="hello world"; print msg}' /etc/passwd
    hello world
    hello world

    awk 声明的变量可以在任何多个花括号脚本中使用

    $ awk 'BEGIN {msg="hello world"} {print msg}' /etc/passwd
    hello world
    hello world

    在 awk 中使用数学运算

    $ awk '{a = 12; b = 24; print a + b}' company.txt
    36
    36
    36
    36

    上面这段脚本表示,先声明两个变量 a = 12 和 b = 24,然后用 print 打印出 a 加上 b 的结果。

    看到上面的输出结果,为什么会重复输出 4 次同样的计算结果。请记住 awk 是针对文件的每一行来执行一次单引号 里面的脚本代码,每读取到一行就会执行一次,文件里面有多少行就会执行多少次,但 BEGIN 和 END 关键字后面的脚本代码除外,如果被处理的文件中什么都没有,那 awk 就一次都不会执行。。。

    awk 还支持其他的数学运算符

    + 加法运算符

    - 减法运算符

    * 乘法运算符

    / 除法运算符

    % 取余运算符

    在 awk 中使用条件判断

    比如有一个文件 company.txt 内容如下

    yahoo   100 4500
    google  150 7500
    apple   180 8000
    twitter 120 5000

    我们要判断文件的第 3 列数据,也就是平均工资小于 5500 的公司,然后将其打印输出

    $ awk '$3 < 5500 {print $0}' company.txt
    yahoo   100 4500
    twitter 120 5000

    上面的命令结果就是平均工资小于 5500 的公司名单, $3 < 5500 表示当第 3 列字段的内容小于 5500 的时候才会执行后面的 {print $0} 代码块

    awk 还有一些其他的条件操作符如下

    < 小于
    <= 小于或等于
    == 等于
    != 不等于
    > 大于
    >= 大于或等于
    ~ 匹配正则表达式
    !~ 不匹配正则表达式

    使用 if 指令判断来实现上面同样的效果 

    $ awk '{if ($3 < 5500) print $0}' company.txt
    yahoo   100 4500
    twitter 120 5000

    上面表示如果第 3 列字段小于 5500 的时候就会执行后面的 print $0,很像 C 语言和 PHP 的语法对不对。 

    在 awk 中使用正则表达式

    比如现在我们有这么一个文件 poetry.txt ,内容如下:

    This above all: to thine self be true
    There is nothing either good or bad, but thinking makes it so
    There’s a special providence in the fall of a sparrow
    No matter how dark long, may eventually in the day arrival

    使用正则表达式匹配字符串 "There" ,将包含这个字符串的行打印并输出

    $ awk '/There/{print $0}' poetry.txt
    There is nothing either good or bad, but thinking makes it so
    There’s a special providence in the fall of a sparrow

    使用正则表达式配一个包含字母 t 和字母 e ,并且 t 和 e 中间只能有任意单个字符的行

    如果只想匹配单纯的字符串 "t.e", 那正则表达式就是这样的 /t.e/ ,用反斜杠来转义 . 符号,因为 . 在正则表达式里面表示任意单个字符。

    $ awk '/t.e/{print $0}' poetry.txt
    There is nothing either good or bad, but thinking makes it so
    There’s a special providence in the fall of a sparrow
    No matter how dark long, may eventually in the day arrival

    正则表达式中的圆括号表示将多个字符当成一个完整的对象来看待。比如 /th(in){1}king/ 就表示其中字符串 "in" 必须出现 1 次。而如果不加圆括号就变成了 /thin{1}king/ 这个就表示其中字符 "n" 必须出现 1 次。

    $ awk '/th(in){1}king/{print $0}' poetry.txt
    There is nothing either good or bad, but thinking makes it so
  • 相关阅读:
    Python3基础 函数 未指定返回值,返回NONE
    Python3基础 函数 有参数有返回值 对传入的参数加1
    Python3基础 函数 无参数无返回值 调用会输出hello world的函数
    Python3基础 函数 收集参数(tuple)+普通参数 的示例
    MVC中几种常用ActionResult
    sqlserver 中存储过程的基础知识记录
    常用的正则表达式方法2
    常用的正则表达式方法1
    vs2012运行项目报未能加载文件或程序集“System.Web.Mvc, Version=4.0.0.1,Culture=neutral”问题和解决方法
    怎样解决PowerDesigner15出现许可证过期问题?
  • 原文地址:https://www.cnblogs.com/wade-luffy/p/6875268.html
Copyright © 2020-2023  润新知