ICode9

精准搜索请尝试: 精确搜索
首页 > 系统相关> 文章详细

linux---awk命令

2021-10-12 21:02:05  阅读:112  来源: 互联网

标签:www 变量 数据字 --- awk linux print root


awk目录

一、什么是awk

虽然sed编辑器是非常方便自动修改文本文件的工具,但其也有自身的限制。通常你需要一个用来处理文件中的数据的更高级工具,它能提供一个类编程环境来修改和重新组织文件中的数据。这正是awk能够做到的。

awk程序是Unix中的原始awk程序的GNU版本。 awk程序让流编辑迈上了一个新的台阶,它提供了一种编程语言而不只是编辑器命令。在awk编程语言中,你可以做下面的事情:

  • 定义变量来保存数据;
  • 使用算术和字符串操作符来处理数据;
  • 使用结构化编程概念(比如if-then语句和循环)来为数据处理增加处理逻辑;
  • 通过提取数据文件中的数据元素,将其重新排列或格式化,生成格式化报告。

awk程序的报告生成能力通常用来从大文本文件中提取数据元素,并将它们格式化成可读的报告。其中最完美的例子是格式化日志文件。在日志文件中找出错误行会很难, awk程序可以让你从日志文件中过滤出需要的数据元素,然后你可以将其格式化,使得重要的数据更易于阅读。

二、awk命令格式

awk程序的基本格式如下

awk options program file

选项描述
-F fs指定行中划分数据字段的字段分隔符
-f file从指定的文件中读取程序
-v var=value定义awk程序中的一个变量及其默认值
-mf N指定要处理的数据文件中的最大字段
-mr N指定数据文件中的最大数据行数
-W keyword指定awk的兼容模式或者警告等级

命令行选项提供了一个简单的途径来定制awk程序中的功能。我们会在探索awk时进一步了解这些选项。
awk的强大之处在于程序脚本。可以写脚本来读取文本行的数据,然后处理并显示数据,创建任何类型的输出报告。

三、awk的基本使用

1)从命令行读取程序脚本

awk程序脚本用一对花括号来定义。你必须将脚本命令放到两个花括号( {})中。如果你错误地使用了圆括号来包含awk脚本,就会得到一条类似于下面的错误提示。

[root@www ~]# awk '(print "hello world!"}'
awk: 命令行:1: (print "hello world!"}
awk: 命令行:1:  ^ syntax error

由于awk命令行假定脚本是单个文本字符串,你还必须将脚本放到单引号中。下面的例子在命令行上指定了一个简单的awk程序脚本:

[root@www ~]# awk '{print "hello world!"}'

这个程序脚本定义了一个命令: print命令。这个命令名副其实:它会将文本打印到STDOUT。如果尝试运行这个命令,你可能会有些失望,因为什么都不会发生。原因在于没有在命令行上指定文件名,所以awk程序会从STDIN接收数据。在运行这个程序时,它会一直等待从STDIN输入的文本。

如果你输入一行文本并按下回车键, awk会对这行文本运行一遍程序脚本。跟sed编辑器一样, awk程序会针对数据流中的每行文本执行程序脚本。由于程序脚本被设为显示一行固定的文本字符串,因此不管你在数据流中输入什么文本,都会得到同样的文本输出。

[root@www ~]# awk '{print "Hello World!"}'
this is a test
Hello World!
haha           
Hello World!
^C

2)使用数据字段变量

awk的主要特性之一是其处理文本文件中数据的能力。它会自动给一行中的每个数据元素分配一个变量。默认情况下, awk会将如下变量分配给它在文本行中发现的数据字段:

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

在文本行中,每个数据字段都是通过字段分隔符划分的。 awk在读取一行文本时,会用预定义的字段分隔符划分每个数据字段。 awk中默认的字段分隔符是任意的空白字符(例如空格或制表符)。

在下面的例子中, awk程序读取文本文件,只显示第1个数据字段的值。

[root@www ~]# cat data2.txt 
One line of test text.
Two lines of test text.
Three lines of test text.
[root@www ~]# awk '{print $1}' data2.txt 
One
Two
Three

该程序用$1字段变量来仅显示每行文本的第1个数据字段。如果你要读取采用了其他字段分隔符的文件,可以用-F选项指定。

[root@www ~]# awk -F: '{print $1}' /etc/passwd | head -3
root
bin
daemon

这个简短的程序显示了系统中密码文件的第1个数据字段。由于/etc/passwd文件用冒号来分隔数字字段,因而如果要划分开每个数据元素,则必须在awk选项中将冒号指定为字段分隔符。

3)在脚本中使用多个命令

如果一种编程语言只能执行一条命令,那么它不会有太大用处。 awk编程语言允许你将多条命令组合成一个正常的程序。要在命令行上的程序脚本中使用多条命令,只要在命令之间放个分号即可。

[root@www ~]# echo "my name is haha" | awk '{$4="xixi";print $0}'
my name is xixi

第一条命令会给字段变量$4赋值。第二条命令会打印整个数据字段。注意, awk程序在输出中已经将原文本中的第四个数据字段替换成了新值。

也可以用次提示符一次一行地输入程序脚本命令。

[root@www ~]# awk '{
> $4="xixi"
> print $0}'
my name is haha
my name is xixi
^C

在你用了表示起始的单引号后, bash shell会使用次提示符来提示你输入更多数据。你可以每次在每行加一条命令,直到输入了结尾的单引号。因为没有在命令行中指定文件名, awk程序会从STDIN中获得数据。当运行这个程序的时候,它会等着读取来自STDIN的文本。要退出程序,只需按下Ctrl+D组合键来表明数据结束。

4)从文件中读取程序

跟sed编辑器一样, awk编辑器允许将程序存储到文件中,然后再在命令行中引用。

[root@www ~]# cat script2.awk 
{print $1 "'s home directory is " $6}
[root@www ~]# awk -F: -f script2.awk /etc/passwd | head -3
root's home directory is /root
bin's home directory is /bin
daemon's home directory is /sbin

script2.awk程序脚本会再次使用print命令打印/etc/passwd文件的主目录数据字段(字段变量$6),以及userid数据字段(字段变量$1)。

可以在程序文件中指定多条命令。要这么做的话,只要一条命令放一行即可,不需要用分号。

[root@www ~]# cat script3.awk 
{
text="'s home directory is "
print $1 text $6
}
[root@www ~]# awk -F: -f script3.awk /etc/passwd | head -3
root's home directory is /root
bin's home directory is /bin
daemon's home directory is /sbin

script3.awk程序脚本定义了一个变量来保存print命令中用到的文本字符串。注意, awk程序在引用变量值时并未像shell脚本一样使用美元符。

5)在处理数据前运行脚本

awk还允许指定程序脚本何时运行。默认情况下, awk会从输入中读取一行文本,然后针对该行的数据执行程序脚本。有时可能需要在处理数据前运行脚本,比如为报告创建标题。 BEGIN关键字就是用来做这个的。它会强制awk在读取数据前执行BEGIN关键字后指定的程序脚本。

[root@www ~]# awk 'BEGIN {print "hellow world!"}'
hellow world!

这次print命令会在读取数据前显示文本。但在它显示了文本后,它会快速退出,不等待任何数据。如果想使用正常的程序脚本中处理数据,必须用另一个脚本区域来定义程序。

[root@www ~]# cat data3.txt
line 1
line 2
line 3
[root@www ~]# awk 'BEGIN {print "the data3 file Contents:"}
> {print $0}' data3.txt
the data3 file Contents:
line 1
line 2
line 3

在awk执行了BEGIN脚本后,它会用第二段脚本来处理文件数据。这么做时要小心,两段脚本仍然被认为是awk命令行中的一个文本字符串。你需要相应地加上单引号。

6)在处理数据后运行脚本

与BEGIN关键字类似, END关键字允许你指定一个程序脚本, awk会在读完数据后执行它。

[root@www ~]# awk 'BEGIN {print "the data3 file contents:"}
> {print $0}
> END {print "end of file"}' data3.txt
the data3 file contents:
line 1
line 2
line 3
end of file

当awk程序打印完文件内容后,它会执行END脚本中的命令。这是在处理完所有正常数据后给报告添加页脚的最佳方法。
可以将所有这些内容放到一起组成一个漂亮的小程序脚本文件,用它从一个简单的数据文件中创建一份完整的报告。

[root@www ~]# cat script4.awk 
BEGIN {
print "the latest list of users and shells"
print "userd \t\t shell"
print "--------\t--------"
FS=":"
}

{
print $1 "     \t "   $7
}
END {
print "this concludes the listing"
}
[root@www ~]# awk -f script4.awk /etc/passwd
the latest list of users and shells
userd 		 shell
--------	--------
root     	 /bin/bash
bin     	 /sbin/nologin
daemon     	 /sbin/nologin
adm     	 /sbin/nologin
....

与预想的一样, BEGIN脚本创建了标题,程序脚本处理特定数据文件( /etc/passwd)中的信息, END脚本生成页脚。

四、awk高级用法

1)使用变量

所有编程语言共有的一个重要特性是使用变量来存取值。awk编程语言支持两种不同类型的变量:

  • 内建变量
  • 自定义变量

awk有一些内建变量。这些变量存放用来处理数据文件中的数据字段和记录的信息。你也可以在awk程序里创建你自己的变量。下面将带你了解如何在awk程序里使用变量。

①、内建变量

awk程序使用内建变量来引用程序数据里的一些特殊功能。

1、字段和记录分隔符变量

之前内容介绍了awk中的一种内建变量类型——数据字段变量。数据字段变量允许使用美元符号( $)和字段在该记录中的位置值来引用记录对应的字段。因此,要引用记录中的第一个数据字段,就用变量$1;要引用第二个字段,就用$2,依次类推。

数据字段是由字段分隔符来划定的。默认情况下,字段分隔符是一个空白字符,也就是空格符或者制表符。之前讲了如何在命令行下使用命令行参数-F或者在awk程序中使用特殊的内建变量FS来更改字段分隔符。

内建变量FS是一组内建变量中的一个,这组变量用于控制awk如何处理输入输出数据中的字段和记录。下表列出了这些内建变量。

变量描述
FIELDWDTHS由空格分隔的一列数字,定义了每个数据字段确切宽度
FS输入字段分隔符
RS输入记录分隔符
OFS输出字段分隔符
ORS输出记录分隔符

变量FS和OFS定义了awk如何处理数据流中的数据字段。之前知道了如何使用变量FS来定义记录中的字段分隔符。变量OFS具备相同的功能,只不过是用在print命令的输出上。
默认情况下, awk将OFS设成一个空格,所以如果你用命令:

print $1,$2,$3

会看到如下输出: field1 field2 field3

在下面的例子里,你能看到这点。

[root@www ~]# cat data1
data11,data12,data13,data14,data15
data21,data22,data23,data24,data25
data31,data32,data33,data34,data35
[root@www ~]# awk 'BEGIN{FS=","} {print $1,$2,$3}' data1
data11 data12 data13
data21 data22 data23
data31 data32 data33

print命令会自动将OFS变量的值放置在输出中的每个字段间。 通过设置OFS变量,可以在输出中使用任意字符串来分隔字段。

[root@www ~]# awk 'BEGIN{FS=",";OFS="-"} {print $1,$2,$3}' data1
data11-data12-data13
data21-data22-data23
data31-data32-data33

[root@www ~]# awk 'BEGIN{FS=",";OFS="<-->"} {print $1,$2,$3}' data1
data11<-->data12<-->data13
data21<-->data22<-->data23
data31<-->data32<-->data33

FIELDWIDTHS变量允许你不依靠字段分隔符来读取记录。在一些应用程序中,数据并没有使用字段分隔符,而是被放置在了记录中的特定列。这种情况下,必须设定FIELDWIDTHS变量来匹配数据在记录中的位置。

一旦设置了FIELDWIDTH变量, awk就会忽略FS变量,并根据提供的字段宽度来计算字段。下面是个采用字段宽度而非字段分隔符的例子。

[root@www ~]# awk 'BEGIN{FIELDWIDTHS="3 5 2 5"}{print $1,$2,$3,$4}' data1
dat a11,d at a12,d
dat a21,d at a22,d
dat a31,d at a32,d

FIELDWIDTHS变量定义了四个字段, awk依此来解析数据记录。每个记录中的数字串会根据已定义好的字段长度来分割。

一定要记住,一旦设定了FIELDWIDTHS变量的值,就不能再改变了。这种方法并不适用于变长的字段。

变量RS和ORS定义了awk程序如何处理数据流中的字段。默认情况下, awk将RS和ORS设为换行符。默认的RS值表明,输入数据流中的每行新文本就是一条新纪录。有时,你会在数据流中碰到占据多行的字段。典型的例子是包含地址和电话号码的数据,其中地址和电话号码各占一行。

Riley Mullen
123 Main Street
Chicago, IL 60601
(312)555-1234

如果你用默认的FS和RS变量值来读取这组数据, awk就会把每行作为一条单独的记录来读取,并将记录中的空格当作字段分隔符。这可不是你希望看到的。

要解决这个问题,只需把FS变量设置成换行符。这就表明数据流中的每行都是一个单独的字段,每行上的所有数据都属于同一个字段。但现在令你头疼的是无从判断一个新的数据行从何开始。

对于这一问题,可以把RS变量设置成空字符串,然后在数据记录间留一个空白行。 awk会把每个空白行当作一个记录分隔符。

下面的例子使用了这种方法。

[root@www ~]# cat data2
Riley Mullen
123 Main Street
Chicago, IL 60601
(312)555-1234

Frank Williams
456 Oak Street
Indianapolis, IN 46201
(317)555-9876

Haley Snell
4231 Elm Street
Detroit, MI 48201
(313)555-4938
[root@www ~]# awk 'BEGIN{FS="\n";RS=""} {print $1,$4}' data2
Riley Mullen (312)555-1234
Frank Williams (317)555-9876
Haley Snell (313)555-4938
2、数据变量

除了字段和记录分隔符变量外, awk还提供了其他一些内建变量来帮助你了解数据发生了什么变化,并提取shell环境的信息。下表列出了awk中的其他内建变量。

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

你应该能从上面的列表中认出一些shell脚本编程中的变量。 ARGC和ARGV变量允许从shell中获得命令行参数的总数以及它们的值。但这可能有点麻烦,因为awk并不会将程序脚本当成命令行参数的一部分。

[root@www ~]# awk 'BEGIN{print ARGC,ARGV[1]}' data1
2 data1

ARGC变量表明命令行上有两个参数。这包括awk命令和data1参数(记住,程序脚本并不算参数)。 ARGV数组从索引0开始,代表的是命令。第一个数组值是awk命令后的第一个命令行参数。

注意:跟shell变量不同,在脚本中引用awk变量时,变量名前不加美元符。

ENVIRON变量看起来可能有点陌生。它使用关联数组来提取shell环境变量。关联数组用文本作为数组的索引值,而不是数值。

数组索引中的文本是shell环境变量名,而数组的值则是shell环境变量的值。下面有个例子。

[root@www ~]# awk '
> BEGIN{
> print ENVIRON["HOME"]
> print ENVIRON["PATH"]
> }'
/root
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin

ENVIRON[“HOME”]变量从shell中提取了HOME环境变量的值。类似地, ENVIRON[“PATH”]提取了PATH环境变量的值。可以用这种方法来从shell中提取任何环境变量的值,以供awk程序使用。

当要在awk程序中跟踪数据字段和记录时,变量FNR、 NF和NR用起来就非常方便。有时你并不知道记录中到底有多少个数据字段。NF变量可以让你在不知道具体位置的情况下指定记录中的最后一个数据字段。

[root@www ~]# awk 'BEGIN{FS=":";OFS=":"} {print $1,$NF}' /etc/passwd
root:/bin/bash
bin:/sbin/nologin
daemon:/sbin/nologin
adm:/sbin/nologin
....

NF变量含有数据文件中最后一个数据字段的数字值。可以在它前面加个美元符将其用作字段变量。

FNR和NR变量虽然类似,但又略有不同。 FNR变量含有当前数据文件中已处理过的记录数,NR变量则含有已处理过的记录总数。让我们看几个例子来了解一下这个差别。

[root@www ~]# awk 'BEGIN{FS","}{print $1,"FNR="FNR}' data1
data11,data12,data13,data14,data15 FNR=1
data21,data22,data23,data24,data25 FNR=2
data31,data32,data33,data34,data35 FNR=3
[root@www ~]# awk 'BEGIN{FS","}{print $1,"FNR="FNR}' data1 data1 data1
data11,data12,data13,data14,data15 FNR=1
data21,data22,data23,data24,data25 FNR=2
data31,data32,data33,data34,data35 FNR=3
data11,data12,data13,data14,data15 FNR=1
data21,data22,data23,data24,data25 FNR=2
data31,data32,data33,data34,data35 FNR=3
data11,data12,data13,data14,data15 FNR=1
data21,data22,data23,data24,data25 FNR=2
data31,data32,data33,data34,data35 FNR=3

在这个例子中, awk程序的命令行定义了两个输入文件(两次指定的是同样的输入文件)。这个脚本会打印第一个数据字段的值和FNR变量的当前值。注意,当awk程序处理第二个数据文件时, FNR值被设回了1。

现在,让我们加上NR变量看看会输出什么。

[root@www ~]# awk '
> BEGIN {FS=","}
> {print $1,"FNR="FNR,"NR="NR}
> END{print "there were",NR,"records processed"}' data1 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
data11 FNR=1 NR=7
data21 FNR=2 NR=8
data31 FNR=3 NR=9
there were 9 records processed

FNR变量的值在awk处理第二个数据文件时被重置了,而NR变量则在处理第二个数据文件时继续计数。结果就是:如果只使用一个数据文件作为输入, FNR和NR的值是相同的;如果使用多个数据文件作为输入, FNR的值会在处理每个数据文件时被重置,而NR的值则会继续计数直到处理完所有的数据文件。

说明:在使用awk时你可能会注意到, awk脚本通常会比shell脚本中的其他部分还要大一些。为了简单起见,在例子中,我们利用shell的多行特性直接在命令行上运行了awk脚本。在shell脚本中使用awk时,应该将不同的awk命令放到不同的行,这样会比较容易阅读和理解,不要在shell脚本中将所有的命令都塞到同一行。还有,如果发现在不同的shell脚本中用到了同样的awk脚本,记着将这段awk脚本放到一个单独的文件中,并用-f参数来在shell脚本中引用它。

②、自定义变量

跟其他典型的编程语言一样, awk允许你定义自己的变量在程序代码中使用。awk自定义变量名可以是任意数目的字母、数字和下划线,但不能以数字开头。重要的是,要记住awk变量名区分大小写。

1、在脚本中给变量赋值

在awk程序中给变量赋值跟在shell脚本中赋值类似,都用赋值语句。

[root@www ~]# awk '
> BEGIN{
> test="this is test"
> print test
> }'
this is test

print语句的输出是test变量的当前值。跟shell脚本变量一样, awk变量可以保存数值或文本值。

[root@www ~]# awk '
> BEGIN{
> test="this is test"
> print test
> test=33
> print test
> }'
this is test
33

在这个例子中, test变量的值从文本值变成了数值。
赋值语句还可以包含数学算式来处理数字值。

[root@www ~]# awk 'BEGIN{x=4; x=x*2+3; print x}'
11

如你在这个例子中看到的, awk编程语言包含了用来处理数字值的标准算数操作符。其中包括求余符号( %)和幂运算符号( ^或**)。

2、在命令行上给变量赋值

也可以用awk命令行来给程序中的变量赋值。这允许你在正常的代码之外赋值,即时改变变量的值。下面的例子使用命令行变量来显示文件中特定数据字段。

[root@www ~]# cat script1
BEGIN{FS=","}
{print $n}
[root@www ~]# awk -f script1 n=2 data1
data12
data22
data32
[root@www ~]# awk -f script1 n=3 data1
data13
data23
data33

这个特性可以让你在不改变脚本代码的情况下就能够改变脚本的行为。第一个例子显示了文件的第二个数据字段,第二个例子显示了第三个数据字段,只要在命令行上设置n变量的值就行。

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

[root@www ~]# cat script2
BEGIN{print "the starting value is",n;FS=","}
{print $n}
[root@www ~]# awk -f script2 n=3 data1
the starting value is 
data13
data23
data33

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

[root@www ~]# awk -v n=3 -f script2 data1
the starting value is 3
data13
data23
data33

2)处理数组

为了在单个变量中存储多个值,许多编程语言都提供数组。 awk编程语言使用关联数组提供数组功能。

关联数组跟数字数组不同之处在于它的索引值可以是任意文本字符串。你不需要用连续的数字来标识数组中的数据元素。相反,关联数组用各种字符串来引用值。每个索引字符串都必须能够唯一地标识出赋给它的数据元素。

①、定义数组变量

可以用标准赋值语句来定义数组变量。数组变量赋值的格式如下:

var[index] = element

其中var是变量名, index是关联数组的索引值, element是数据元素值。下面是一些awk中数组变量的例子。

capital[“Illinois”] = “Springfield”
capital[“Indiana”] = “Indianapolis”
capital[“Ohio”] = “Columbus”

在引用数组变量时,必须包含索引值来提取相应的数据元素值。

[root@www ~]# awk 'BEGIN{
> capital["Illinois"] = "Springfield"
> print capital["Illinois"]
> }'
Springfield

在引用数组变量时,会得到数据元素的值。数据元素值是数字值时也一样。

[root@www ~]# awk 'BEGIN{
> var[1] = 34
> var[2] = 3
> total = var[1] + var[2]
> print total
> }'
37

正如你在该例子中看到的,可以像使用awk程序中的其他变量一样使用数组变量。

1、遍历数组变量

关联数组变量的问题在于你可能无法知晓索引值是什么。跟使用连续数字作为索引值的数字数组不同,关联数组的索引可以是任何东西。

如果要在awk中遍历一个关联数组,可以用for语句的一种特殊形式。

for (var in array)
{
statements
}

这个for语句会在每次循环时将关联数组array的下一个索引值赋给变量var,然后执行一遍statements。重要的是记住这个变量中存储的是索引值而不是数组元素值。可以将这个变量用作数组的索引,轻松地取出数据元素值。

[root@www ~]# awk 'BEGIN{
> var["a"] = 1
> var["g"] = 2
> var["m"] = 3
> var["u"] = 4
> for (test in var)
> {
> print "Index:",test,"- Value:",var[test]
> }
> }'
Index: u - Value: 4
Index: m - Value: 3
Index: a - Value: 1
Index: g - Value: 2

注意,索引值不会按任何特定顺序返回,但它们都能够指向对应的数据元素值。明白这点很重要,因为你不能指望着返回的值都是有固定的顺序,只能保证索引值和数据值是对应的。

2、删除数组变量

delete array[index]

删除命令会从数组中删除关联索引值和相关的数据元素值。

[root@www ~]# awk 'BEGIN{
> var["a"] = 1
> var["g"] = 2
> for (test in var)
> {
> print "Index:",test," - Value:",var[test]
> }
> delete var["g"]
> print"---"
> for (test in var)
> {
> print "Iindex:",test," - Value",var[test]
> }
> }'
Index: a  - Value: 1
Index: g  - Value: 2
---
Iindex: a  - Value 1

一旦从关联数组中删除了索引值,你就没法再用它来提取元素值。

②、使用模式

awk程序支持多种类型的匹配模式来过滤数据记录,这一点跟sed编辑器大同小异。BEGIN和END关键字是用来在读取数据流之前或之后执行命令的特殊模式。类似地,你可以创建其他模式在数据流中出现匹配数据时执行一些命令。

1、正则表达式

前面介绍了如何将正则表达式用作匹配模式。可以用基础正则表达式( BRE)或扩展正则表达式( ERE)来选择程序脚本作用在数据流中的哪些行上。在使用正则表达式时,正则表达式必须出现在它要控制的程序脚本的左花括号前。

[root@www ~]# awk 'BEGIN{FS=","} /11/{print $1}' data1
data11

正则表达式/11/匹配了数据字段中含有字符串11的记录。 awk程序会用正则表达式对记录中所有的数据字段进行匹配,包括字段分隔符。

[root@www ~]# awk 'BEGIN{FS=","} /,d/{print $1}' data1
data11
data21
data31

这个例子使用正则表达式匹配了用作字段分隔符的逗号。这也并不总是件好事。它可能会造成如下问题:当试图匹配某个数据字段中的特定数据时,这些数据又出现在其他数据字段中。如果需要用正则表达式匹配某个特定的数据实例,应该使用匹配操作符。

2、匹配操作符

匹配操作符( matching operator)允许将正则表达式限定在记录中的特定数据字段。匹配操作符是波浪线( ~)。可以指定匹配操作符、数据字段变量以及要匹配的正则表达式。

$1 ~ /^data/

$1变量代表记录中的第一个数据字段。这个表达式会过滤出第一个字段以文本data开头的所有记录。下面是在awk程序脚本中使用匹配操作符的例子。

[root@www ~]# awk 'BEGIN{FS=","} $2 ~ /^data2/{print $0}' data1
data21,data22,data23,data24,data25

匹配操作符会用正则表达式/^data2/来比较第二个数据字段,该正则表达式指明字符串要以文本data2开头。

这可是件强大的工具, awk程序脚本中经常用它在数据文件中搜索特定的数据元素。

[root@www ~]# awk -F: '$1 ~ /redhat/{print $1,$NF}' /etc/passwd
redhat /bin/bash

这个例子会在第一个数据字段中查找文本redhat。如果在记录中找到了这个模式,它会打印该记录的第一个和最后一个数据字段值。

也可以用!符号来排除正则表达式的匹配。

$1 !~ /expression/

如果记录中没有找到匹配正则表达式的文本,程序脚本就会作用到记录数据。

[root@www ~]# awk -F: '$1 !~ /redhat/{print $1,$NF}' /etc/passwd
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
....

在这个例子中, awk程序脚本会打印/etc/passwd文件中与用户ID redhat不匹配的用户ID和登录shell。

数学表达式

除了正则表达式,你也可以在匹配模式中用数学表达式。这个功能在匹配数据字段中的数字值时非常方便。举个例子,如果你想显示所有属于root用户组(组ID为0)的系统用户,可以用这个脚本。

[root@www ~]# awk -F: '$4 == 0 {print $1}' /etc/passwd
root
sync
shutdown
halt
operator

标签:www,变量,数据字,---,awk,linux,print,root
来源: https://blog.csdn.net/qq_43773590/article/details/119818719

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有