深入浅出Linux工具与编程
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第2章 Linux常用实用工具

本章列出了Linux常用的几种实用工具,其中正则表达式符号的含义和find工具较为常用,对于sed的内容,读者只需了解即可,对awk则需重点掌握实例练习的打印记录部分。

2.1 正则表达式

正则表达式完成字符串的匹配搜索,可以对满足匹配条件的特定匹配串进行替换等处理。

在UNIX系统中,sed、grep、vi等工具都使用regexp(正则表达式英文缩写)规则。

开源软件的perl、cygwin也提供了在Windows系统中使用regexp规则的工具。

1.正则表达式概述

空格、字母、数字可以直接作为正则表达式的字符匹配。对于特殊字符,可以使用\符号转义取得。

2.正则表达式基本语法

表2-1列出了正则表达式的符号及其含义,这些符号是正则表达式最基本、最常用的语法。

表2-1 正则表达式基本语法

3.正则表达支持POSIX字符集合

表2-2列出了正则表达式POSIX字符集合及其含义,POSIX字符集合较少使用,读者只需了解即可。

表2-2 正则表达式POSIX字符集合

4.正则表达式的转义字符

表2-3列出了正则表达式的转义字符及其含义,这些转义字符较少使用,读者只需了解即可。

表2-3 正则表达式的转义字符

2.2 find查找命令

find是查找特定特征文件的一个工具。

find常用命令为:

    find /home/test  -name  aa.sh –print

表示在/home/test目录下查找名称为aa.sh的文件,并把路径打印出来。

2.2.1 find语法

1.find命令语法形式

find命令的语法形式如下:

    find pathname -options [-print -exec -ok]

参数介绍如下。

[1]pathname:find命令所查找的目录路径。可以用.表示当前目录,用/表示系统根目录。

[2]-options:表示选项。

[3]-print:find命令将匹配的文件输出到标准输出。

[4]-exec:find命令对匹配的文件执行该参数所给出的Shell命令。相应命令的形式为'command' _{} \; 。注意,{}和\;之间有空格。

[5]-ok:它和-exec的作用相同,只不过以一种更安全的模式来执行该参数所给出的Shell命令,在执行每一个命令之前都会给出提示,让用户来确定是否执行。

2.find命令选项(options)

find命令有很多选项或表达式,每一个选项前面跟随一个横杠(-),下面是find的主要选项。

[1]-name:按照文件名查找文件。

[2]-perm:按照文件权限来查找文件。

[3]-prune:使用这一选项可以使find命令不在当前指定的目录中查找,如果同时使用了-depth选项,那么-prune选项将被find命令忽略。

[4]-user:按照文件属主来查找文件。

[5]-group:按照文件所属的组来查找文件。

[6]-mtime -n +n:按照文件的更改时间来查找文件,-n表示文件更改时间距现在n天以内,+n表示文件更改时间距现在n天以前。find命令还有-atime和-ctime选项,但它们都和 -mtime选项相似,所以在这里只介绍-mtime选项。

[7]-nogroup:查找无有效所属组的文件,即该文件所属的组在/etc/groups中不存在。

[8]-nouser:查找无有效属主的文件,即该文件的属主在/etc/passwd中不存在。

[9]-newer file1 ! file2:查找更改时间比文件file1新但比文件file2旧的文件。

[10]-type:查找某一类型的文件,诸如:

█ b:块设备文件。

█ d:目录。

█ c:字符设备文件。

█ p:管道文件。

█ l:符号链接文件。

█ f:普通文件。

[11]-size n[c]:查找文件长度为n块的文件,带有c时表示文件长度以字节计算。

[12]-depth:在查找文件时,首先查找当前目录中的文件,然后在其子目录中查找。

[13]-fstype:查找位于某一类型文件系统中的文件,这些文件系统类型通常可以在配置文件/etc/fstab中找到,该配置文件中包含了本系统中有关文件系统的信息。

[14]-mount:在查找文件时不跨越文件系统mount点。

[15]-follow:如果find命令遇到符号链接文件,就跟踪至链接所指向的文件。

[16]-cpio:对匹配的文件使用cpio命令,将这些文件备份到磁带设备中。

2.2.2 find实例练习

1.使用name选项

[1]查找$HOME目录下后缀以.txt结尾的文件。

    $ find  ~  -name "*.txt"  -print

[2]在当前目录及子目录中查找文件名以一个大写字母开头的文件。

    $ find . -name "[A-Z]*" -print

[3]在/etc目录中查找文件名以host开头的文件。

    $ find /etc -name "host*" -print

[4]查找文件名以两个小写字母开头,后跟两个数字的文件,如aa37.txt。

    $ find . -name "[a-z][a-z][0-9][0-9].txt" -print
2.使用perm选项

在当前目录下查找文件权限位为755的文件。

    $ find . -perm 755 -print
3.忽略某个目录

希望在/apps目录下查找文件,但不希望在/apps/bin目录下查找。

    $ find /apps -name "/apps/bin" -prune -o -print
4.使用user和nouser选项

[1]在$HOME目录中查找文件属主为dave的文件。

    $ find  ~  -user dave -print

[2]在/etc目录下查找文件属主为uucp的文件。

    $ find /etc -user uucp  -print

[3]为了查找属主账户已经被删除的文件,可以使用 -nouser选项。

    $ find /home -nouser -print
5.使用nogroup选项

要查找没有有效所属用户组的所有文件,可以使用nogroup选项,其格式如下:

    $ find  /  -nogroup   -print
6.按照更改时间查找文件

[1]在系统根目录下查找更改时间在5日以内的文件。

    $ find /-mtime -5 -print

[2]在/var/adm目录下查找更改时间在3日以前的文件。

    $ find  /var/adm  -mtime +3 -print
7.查找比某个文件新或旧的文件

查找某个时间点之前的文件,例如:

    $ touch –t 09101119 dstamp   ——创建一个文件的时间为9月10日11点19分
    $ find . -newer dstamp –print——查找该时间点之前的文件
8.使用type选项

[1]查找/etc目录下所有的目录。

    $ find /etc -type d -print

[2]在/etc目录下查找所有的符号链接文件。

    $ find /etc -type l -print
9.使用size选项

[1]在当前目录下查找文件长度大于1MB的文件。

    $ find . -size +1000000c -print
    $ find /home/apache -size 100c -print

[2]在/home/apache目录下查找文件长度恰好为100B的文件。

[3]在当前目录下查找长度超过10块的文件。

    $ find . -size +10 -print
10.使用exec或ok

当匹配到一些文件以后,可能希望对其进行某些操作,这时就可以使用-exec选项。exec选项后面跟所要执行的命令,然后是一对花括号{}、一个空格和一个反斜杠\,最后是一个分号。

[1]利用ls -l列出所找到的文件。

    $ find . -type  f -exec ls -l {} \;

[2]删除5天以前的日志。

    $ find . -name  "*.LOG" -mtime +5 -ok rm {} \;
    $ find /home/hap/src/* -name "*.o" -exec rm {} \;
11.使用xargs

在使用find命令的-exec选项处理匹配到的文件时,find命令将所有匹配到的文件一起传递给exec执行。但由于有些系统对能够传递给exec的命令长度有限制,这样在find命令运行几分钟之后,就会出现溢出错误。错误信息通常是“参数列太长”或“参数列溢出”。这就是xargs命令的用处所在,常与find命令一起使用。

用grep命令在所有的普通文件中搜索device单词。

    $ find  / -type f -print — xargs grep "device"

2.3 sed

sed是一个非交互性文本流编辑器,使用sed可以从文件和字符串中抽取所需信息。

2.3.1 sed语法

1.sed的三种调用格式

sed具有以下三种调用格式。

[1]命令行方式:

    sed  [选项]  sed命令  输入文件

[2]sed脚本文件:

    含sed命令脚本文件 [选项] 输入文件

[3]sed调用脚本文件:

    sed [选项] -f 不含sed命令的脚本文件 输入文件
2.sed的选项

sed选项说明如下。

[1]-n:不打印,sed不写编辑行到标准输出。sed默认为打印所有的行,即编辑的行和未编辑的行,可以用p命令打印需要显示的行。

[2]-c:下一命令是编辑命令。使用多项编辑时可加入此选项,如果只用到一条sed命令,此选项无用,但指定它也没有关系。

[3]-f:调用sed脚本文件。此选项表示sed的一个脚本文件支持所有的sed命令。例如:sed -f myscript.sed input_file,这里的myscript.sed为支持sed命令的文件。

3.sed定位文本的方式

利用sed浏览文件时,默认从第一行开始,有以下两种形式定位文本。

█ 使用行号:用一个数字表示该行号,使用两个数字表示行号范围。

█ 使用正则表达式。

表2-4给出了sed定位文本的方式。

表2-4 sed定位文本的方式

4.sed基本编辑命令

表2-5列出了sed的编辑命令。

表2-5 sed编辑命令

5.sed的常用操作

表2-6列出了sed的一些常用操作,其中,[]表示空格,[ ]表示tab键。

表2-6 sed的一些常用操作

2.3.2 sed实例练习

1.sed练习文档

使用vi sed.txt命令录入如下内容,然后保存。

    BUGS Setuid shell scripts should be avoided at all costs.
        PS1, PS2, and PS4 should be subject to parameter
    BSD         January 19, 2003
2.打印范围

(1)打印第2行

    $ Linux:  sed -n  '2p' sed.txt
        PS1, PS2, and PS4 should be subject to parameter

(2)打印第1~3行

    $ Linux:  sed -n  '1,3p' sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
        PS1, PS2, and PS4 should be subject to parameter

(3)将第1~3行输入到sed.tmp中

    $ Linux:sed -n  '1,3p'  sed.txt > sed.tmp

(4)显示全文

    $ Linux: sed -n  '1, $p' sed.txt

(5)打印首行

    $ Linux:  sed -n  '1p' sed.txt

(6)打印最后一行

    $ Linux: sed -n  ' $p' sed.txt

(7)–n参数意义

测试sed '2p' sed.txt。我们希望输出第2行,但sed默认输出编辑文本,所以输出了全部文本,并把第2行又多输出一次。所以,sed一般要加上-n参数,让标准输入不输出到屏幕上,只输出产生的结果。

3.使用模式查询

(1)查找should的行

    $ Linux: sed -n  ' /should/' p  sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
        PS1, PS2, and PS4 should be subject to parameter

(2)输出匹配的行号

    $ Linux: sed -n  ' /should/='  sed.txt
    1
    2
4.特殊字符查询

说明:特殊字符匹配需要用\进行转义。

若要查找有.的行,则命令如下:

    $ Linux: sed -n  ' /\./' p  sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
5.删除文本

(1)删除第1~3行

    $ Linux: sed  '1,3d'  sed.txt
    BSD         January 19,2003

(2)删除含有should的行

    $ Linux: sed  ' /should/d'  sed.txt
    BSD         January 19,2003
6.替换文本

(1)替换每行第一个单词

    $ Linux:sed  ' s/PS/ps/' sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
        ps1, PS2, and PS4 should be subject to parameter
    BSD         January 19,2003

(2)全文替换(/g参数)

    $ Linux:sed  ' s/PS/ps/g' sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
        ps1, ps2, and ps4 should be subject to parameter
    BSD         January 19,2003

(3)指定行替换

    $ Linux:sed  '1,3 s/should/SHOULD/g' sed.txt
    BUGS Setuid shell scripts SHOULD be avoided at all costs.
        ps1, ps2, and ps4 SHOULD be subject to parameter
    BSD         January 19,2003

(4)指定行范围替换

    $ Linux:sed  '1 s/should/SHOULD/g' sed.txt
    BUGS Setuid shell scripts SHOULD be avoided at all costs.
        ps1, ps2, and ps4 should be subject to parameter
    BSD         January 19,2003
7.sed脚本文件

(1)含sed命令的脚本(sed执行的第二种方式)

Shell中#!表示脚本使用哪种命令执行。

    $ Linux:cat appsed.sed
    #! /bin/sed -f
    /should/a\
    Then suddenly it happened.
    $ Linux:chmod +x appsed.sed
    $ Linux:./appsed.sed sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
    Then suddenly it happened.
        PS1, PS2, and PS4 should be subject to parameter
    Then suddenly it happened.
    BSD         January 19, 2003

(2)不含sed命令脚本(sed执行的第三种方式)

    $ Linux:cat app.sed
    3 a\
    Then suddenly it happened.
    $ Linux:chmod +x app.sed
    $ Linux:sed -f app.sed sed.txt
    BUGS Setuid shell scripts should be avoided at all costs.
        PS1, PS2, and PS4 should be subject to parameter
    Then suddenly it happened.
    BSD         January 19, 2003
8.控制字符的输入

在使用sed命令时,有时需要对控制字符(回车、Esc等)进行操作,其输入方法如下,以输入回车(^M )为例。

[1]同时按下Ctrl键和V键。

[2]按下M键,释放Ctrl键。

[3]回车字符输入完成。

[4]控制字符替换与其他普通字符相同。

2.4 awk

awk是一种编程语言,对文本和数据进行处理,支持正则表达式,突出特点是对文本列的操作。

awk有三个不同版本:awk、nawk和gawk,三个版本功能基本相同,gawk是awk的GNU版本,未做特别说明,一般指gawk。

awk语言的最基本功能是在文件或字符串中基于指定规则来分解抽取信息,也可以基于指定的规则来输出数据。

2.4.1 awk语法

1.awk调用的三种方式

awk调用有三种方式,分别为命令行方式、脚本执行方式和命令行调用脚本执行方式,三种方式具体说明如下。

(1)awk [option] ' awk_script' input_file1 [input_file2 ...] awk的常用选项option有:

[1]-F fs:使用fs作为输入记录的字段分隔符,如果省略该选项,awk使用环境变量FS的值(默认为空格)。

[2]-f filename:从文件filename中读取awk_script(awk脚本)。

[3]-v var=value:为awk_script设置变量。

(2)将awk_script放入脚本文件并以#! /bin/awk -f作为首行,给予该脚本可执行权限,然后在Shell命令行下通过键入该脚本的脚本名进行执行。

(3)将所有的awk_script写入到一个单独脚本文件,然后调用“awk -f awk脚本文件 输入文件列表”进行执行。

2.awk样例文本

为了在语法中举例,先建立两个awk文本,名称分别为grade.txt和passwd。

grade.txt文本文件记录了一个柔道信息库,此文本文件有七个域(即七列),域意义分别为(1)名字、(2)升段日期、(3)学生序号、(4)腰带级别、(5)年龄、(6)目前比赛积分、(7)比赛最高分。grade.txt内容如下:

      M.Tansley  05/99  48311  Green    8   40  44
      J.Lulu    06/99  48317  green    9   24  26
      P.Bunny   02/99  48    Yellow   12  35  28
      J.Troll   07/99  4842   Brown-3   12  26  26
      L.Tansley  05/99  4712   Brown-2   12  30  28

passwd以“:”分隔每列,文件内容如下:

      root:x:0:0:root:/root:/bin/bash
      daemon:x:1:1:daemon:/usr/sbin:/bin/sh
3.记录和域

(1)域分隔符

域分隔符:文本列与列的分隔符,默认是空格或Tab。内置变量FS保存输入域分隔符值。

输出域的分隔符默认是一个空格,保存在内置变量OFS中。

修改输入域分隔符方法为:awk -F ' [:\t]' ' {print $1, $3}' passwd,此例表示以空格、冒号和Tab键为分隔符。

(2)记录

记录:awk把每一个以换行符结束的行称为一个记录。

记录分隔符:默认的输入和输出的记录分隔符都是换行,保存在内置变量ORS和RS中。

变量NR:一个计数器,每处理完一条记录,NR的值就增加1。

例:awk' {print NR, $0}' grade.txt,此样例将打印行号和整行内容。

(3)域

域:记录中每一列叫做域。

域标志顺序为$1, $2, …, $n。$0表示整条记录,$1表示当前行第1列,$n表示当前行第n列。

域之间的分隔符默认为空格或Tab,可以用-F参数修改域分隔符。

例:awk ' {print $1, $3}' grade.txt

此样例为打印此文本第1列和第3列内容。$1与$3之间的逗号将使两列产生空格分隔符,若无逗号则两列会连在一起。

例:awk ' { print $1 "—" $3}' grade.txt > grade1.txt

此样例让两列用—分隔,并输出到grade1.txt文件中。

4.awk_script说明

(1)模式与操作语法说明

awk脚本(awk_script)由模式和操作组成。

格式为:pattern {action},其中,pattern为模式,action为操作。

两者是可选的,如果没有pattern,则action应用到全部记录,如果没有action,则输出匹配的全部记录。

默认情况下,每一个输入行都是一条记录,但用户可通过RS变量指定不同的分隔符进行分隔。

(2)模式种类

[1]/正则表达式/:使用正则表达式通配符的扩展集。常用通配符如下:

\ ^ $ . [] — () * //通用的regexp元字符。

+ :匹配其前的单个字符一次以上。

? :匹配其前的单个字符1次或0次。

[2]关系表达式。

[3]模式匹配表达式:用运算符~(匹配)和~! (不匹配)。

[4]范围模式:指定一个行的范围,该语法不能包括BEGIN和END模式。

[5]BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。

[6]END:让用户在最后一条输入记录被读取之后发生的动作。

(3)操作种类

操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要有四部分:变量或数组赋值、输出命令、内置函数、控制流命令。

5.awk的运行过程

(1)awk_script的组成

awk_script可以由一条或多条awk_cmd组成,两条awk_cmd之间一般以换行分隔。

awk_cmd由两部分组成:awk_pattern { action }。

awk_script可以分成多行书写,必须确保整个awk_script被单引号引起来。

(2)awk命令的一般形式

awk命令的一般形式如下:

    awk  ' BEGIN { action }
    awk_pattern1 { action }
    ............
    awk_patternN { action }
    END { action }
    ' inputfile

其中,BEGIN { action } 和END { action } 是可选的。

(3)awk的运行过程

[1]如果BEGIN区块存在,awk执行它指定的action。

[2]awk从输入文件中读取一行,称为一条输入记录(如果输入文件省略,将从标准输入读取)。

[3]awk将读入的记录分割成字段,将第1个字段放入变量$1中,第2个字段放入$2,依此类推,$0表示整条记录。字段分隔符使用变量IFS或由参数指定。

[4]把当前输入记录依次与每一个awk_cmd中awk_pattern比较,看是否匹配,如果相匹配,就执行对应的action,如果不匹配,就跳过对应的action,直到比较完所有的awk_cmd。

[5]当一条输入记录比较了所有的awk_cmd后,awk读取输入的下一行,继续重复步骤③和④,这个过程一直持续,直到awk读取到文件尾。

[6]当awk读完所有的输入行后,如果存在END,就执行相应的action。

(4)inputfile可以是多于一个文件的文件列表,awk将按顺序处理列表中的每个文件。

6.awk内置变量与内置函数说明

(1)awk的内置变量

表2-7列出了awk内置变量,这些内置变量表示特定的含义,可以在awk脚本中直接使用。

表2-7 awk内置变量表

(2)awk内置字符串函数

表2-8列出了awk内置字符串函数及其说明。

表2-8 awk内置字符串函数表

7.awk编程语法详细说明

(1)awk变量

[1]在awk中,变量不需要定义就可以直接使用,变量类型可以是数字或字符串。

[2]awk赋值格式为:Variable=expression。例如,$awk ' $1 ~/test/{count = $2+ $3; print count}' test,上式的作用是,awk先扫描第一个域,一旦test匹配,就把第二个域的值加上第三个域的值,并把结果赋值给变量count,最后打印出来。

[3]域变量可被赋值和修改。例如,$awk ' {$2=100+$1; print $2}' test,上式表示如果第二个域不存在,awk将计算表达式100加$1的值,并将其赋值给$2,如果第二个域存在,则用表达式的值覆盖$2原来的值。

[4]可以使用内置变量。例如,$awk ' { if($1=="MARY"){print NR, $1, $2, $NF}}' test,该例含义为打印MARY的记录数、第一个域、第二个域和最后一个域。

(2)awk数组

awk中数组叫做关联数组,因为下标可以是数也可以是字符串。awk中的数组不必提前声明,也不必声明大小。数组元素用0或空串来初始化,这根据上下文而定。

[1]可以用数值作为数组索引(下标)。

    Myarray[1]= "xu sihua"
    Myarray[2]= "780927"

[2]可以用字符串作为数组索引(下标)。

    Myarray["first"]="xu"
    Myarray["birth"]="780927"

(3)awk语句

awk有如下几种语句:

[1]条件语句:if语句、if-else语句,用法与C语言同名语句相同。

[2]循环语句:while循环、for循环、do-while循环、special for循环。while循环、do-while循环、for循环语句用法与C语言中同名语句相同。

[3]跳转语句:break和continue语句,作用和语法也与C语言同名语句相同。

[4]next语句:从输入文件中读取一行,然后从头开始执行awk脚本。

[5]exit语句:用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。

[6]special for循环语法:与Shell语法for循环类似,表示变量在数组中开始循环。special for语法格式如下:

    for (item in arrayname){
      print arrayname[item]
    }

(4)awk函数

awk函数分为系统自带函数和用户自定义函数。print函数和printf函数为awk的系统自带打印函数。其中,print函数为awk常见的打印函数,如果需要打印复杂的格式,可以使用printf函数,此函数用法几乎与C语言中printf函数相同。

在awk中自定义函数格式如下:

    function name ( parameter, parameter, parameter, ... )
    {
          statements
          return expression
     }

(5)awk特殊字符

表2-9列出了awk特殊字符及其说明。

表2-9 awk特殊字符表

(6)awk运算符

表2-10列出了awk运算符及其说明。

表2-10 awk运算符表

(7)awk注意事项

[1]确保整个awk_script用单引号引起来。

[2]确保awk_script内所有引号成对出现。

[3]确保用花括号引起动作语句,用圆括号括起条件语句。

[4]如果使用字符串,一定要保证字符串被双引号引起来(在模式中除外)。

2.4.2 awk实例练习

1.awk的常见操作

下面是实际工作中利用awk工具常用的两种操作。

[1]默认分隔符为空格打印相应列:awk ' {print $1, $3}' grade.txt

[2]指定分隔符打印相应列:awk -F ' [:\t]' ' {print $1, $3}' passwd

2.打印记录

(1)打印grade.txt所有记录

    $ Linux: awk ' {print $0 }' grade.txt
     M.Tansley  05/99  48311  Green    8   40  44
    J.Lulu    06/99  48317  green    9   24  26
    P.Bunny   02/99  48    Yellow   12  35  28
    J.Troll   07/99  4842   Brown-3   12  26  26
    L.Tansley  05/99  4712   Brown-2   12  30  28

(2)打印passwd的第1列和第3列

    $ Linux: awk -F: ' {print $1, $3}' passwd
    root 0
    daemon 1

(3)打印报告头

    $ Linux:awk ' BEGIN {print "Name Belt\n----------"}
          {print $1"\t"$3}' grade.txt

结果如下:

    Name Belt
    ----------
    M.Tansley      48311
    J.Lulu  48317
    P.Bunny 48
    J.Troll 4842
    L.Tansley      4712

(4)打印报告尾

    $ Linux:awk ' BEGIN { print "Name \n -----"}{print $1} END { print "end-of-
  report" }' grade.txt
    Name
    -----
    M.Tansley
    J.Lulu
    P.Bunny
    J.Troll
    L.Tansley
    end-of-report
3.条件运算符

(1)匹配

匹配grade.txt文本域4为Brown的项。

    $ Linux:awk ' {if ( $4~/Brown/) print $0}' grade.txt
    J.Troll   07/99  4842   Brown-3   12  26  26
    L.Tansley  05/99  4712   Brown-2   12  30  28

不匹配使用“! ~”。

(2)精确匹配

精确匹配第3个域为48。

    $ Linux: awk ' $3=="48" {print $0}' grade.txt
    P.Bunny   02/99  48    Yellow   12  35  28

精确不匹配使用“! =”。

(3)字段比较

>(大于)、<(小于)、<=(小于等于)、>=(大于等于)使用方法差不多,故在这里只举一例:如果第7个域大于第6个域,则打印第1个域和提示信息。

    $ Linux: awk ' {if ($6 < $7){  print $1, "Try better at the next comp" }}' grade.txt
    M.Tansley Try better at the next comp
    J.Lulu Try better at the next comp
4.利用正则表达式

(1)匹配字符大小写

匹配Green或者green。

    $ Linux: awk  ' /[Gg]reen/' grade.txt
    M.Tansley  05/99  48311  Green    8   40  44
    J.Lulu    06/99  48317  green    9   24  26

(2)匹配任意字符

匹配第一个域的第4个字符为a,前三个字符为任意。本例^符号代表行首,.表示匹配任意字符。

    $ Linux: awk ' $1~/^...a/' grade.txt
    M.Tansley  05/99  48311  Green    8   40  44
    L.Tansley  05/99  4712   Brown-2   12  30  28

(3)或关系匹配

匹配Yellow或Brown的行。

    $ Linux: awk ' $0~/(Yellow—Brown)/' grade.txt
    P.Bunny   02/99  48    Yellow   12  35  28
    J.Troll   07/99  4842   Brown-3   12  26  26
    L.Tansley  05/99  4712   Brown-2   12  30  28

(4)复合匹配关系

复合匹配关系有如下三种:

[1]&&(AND):语句两边必须同时匹配为真。

[2]——(OR):语句至少一边匹配为真。

[3]! (非):进行逆运算。

打印出第1域为“P.Bunny”和第4域为“Yellow”的行。

    $ Linux: awk ' { if ( $1=="P.Bunny" && $4=="Yellow" ) print $0 }' grade.txt
    P.Bunny   02/99  48    Yellow   12  35  28
5.使用内置变量

下面用到的内置变量NF为列数,内置变量NR为行号。

    $ Linux: awk ' {print NF, NR, $0} END {print FILENAME}' grade.txt
    7 1 M.Tansley  05/99  48311  Green    8   40  44
    7 2 J.Lulu    06/99  48317  green    9   24  26
    7 3 P.Bunny   02/99  48    Yellow   12  35  28
    7 4 J.Troll   07/99  4842   Brown-3   12  26  26
    7 5 L.Tansley  05/99  4712   Brown-2   12  30  28
    grade.txt
6.使用内置字符串函数

(1)gsub函数

把有4842的行中的4842替换为4899。

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

(2)index函数

找出字符串的位置。

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

(3)macth函数

    $ Linux:awk ' BEGIN {print match("ABCD", /C/)}' grade.txt
    3

(4)split函数

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

这个例子中,split返回数组myarray的下标数。myarray取值如下:myarray[1]为123、myarray[2]为456、myarray[3]为678。

7.输出函数printf

利用printf函数进行复杂格式输出。

    $ Linux: awk ' { printf "%-15s %s\n", $1, $3}' grade.txt
    M.Tansley      48311
    J.Lulu         48317
    P.Bunny        48
    J.Troll        4842
    L.Tansley      4712