AWK介绍及使用方法
预定义变量
-
awk将程序的输入分为记录和字段。 它跟踪从当前输入文件到目前为止已读取的记录数。 该值存储在名为
FNR
的预定义变量中,每次启动新文件时该变量都将重置为零。 另一个预定义的变量NR
记录了到目前为止已从所有数据文件读取的输入记录的总数。 它从零开始,但永远不会自动重置为零。 -
NF
:表示的是浏览记录的域(以空格为默认间隔符则表示列)的个数
$NF
:表示的最后一个Field(列),即输出最后一个字段的内容 -
awk函数的
split(s, a, sep)
使用分隔符sep
将字符串s
拆分为数组a
。 -
tail&cat
tail 功能:显示指定文件的后若干行。
语法:tail [+ / - num ] [参数]
文件
tail命令中各个选项的含义为:
+num
从第num
行以后开始显示。- num
从距文件尾num
行处开始显示。如果省略num
参数,系统默认值为10。l
以文本行为num
的计数单位。与参数选项+num
或- num
选项同时使用时,num
表示要显示的文本行行数。c
以字节为num
的计数单位。与参数选项+num
或- num
选项同时使用时,num
表示要显示的字符数。(l、c选项可以省略,系统默认值为l,即按行计数)。- 使用tail命令的
-f
选项可以方便的查阅正在改变的日志文件,tail -f filename
会把filename
里最尾部的内容显示在屏幕上,并且不但刷新,使你看到最新的文件内容。
cat主要有三大功能:
-
一次显示整个文件。
$ cat filename
-
从键盘创建一个文件。
$ cat > filename
只能创建新文件,不能编辑已有文件.
-
将几个文件合并为一个文件。
$cat file1 file2 > file
-
paste的用法
-d<间隔字符>或–delimiters=<间隔字符> :用指定的间隔字符取代跳格字符。
AWK介绍
- awk的基本功能是在文件中搜索包含某些模式的行(或其他文本单位)。 当一行与其中一种模式匹配时,awk在该行上执行指定的操作。 awk继续以这种方式处理输入行,直到到达输入文件的末尾。
- awk中的程序与大多数其他语言中的程序不同,因为awk程序是数据驱动的(即,描述要使用的数据,然后找到要处理的数据)。 其他大多数语言都是程序性语言; 必须详细描述程序应采取的每个步骤。 使用过程语言时,通常很难清楚地描述程序将要处理的数据。 因此,awk程序通常很容易阅读和编写。
- 当运行awk时,可以指定一个awk程序来告诉awk该怎么做。 该程序由一系列规则组成(它可能还包含函数定义,这是我们暂时将忽略的高级功能;请参阅 User-Defined Functions一节)。 每个规则指定一个要搜索的模式,并在找到该模式时执行一个动作。
- 从句法上讲,规则由一个模式和一个动作组成。 该动作用大括号括起来,以将其与模式分开。 换行符通常是分开的规则。 因此,awk程序如下所示:
pattern { action } pattern { action } …
一些简单的例子
-
以下命令运行一个简单的awk程序,该程序在输入文件mail-list中搜索字符串
li
(一组字符通常称为字符串;术语string基于英语中的类似用法,例如,a string of pearls or a string of cars in a train):awk '/li/ { print $0 }' mail-list
当找到包含
li
的行时,将打印它们,因为print $0
表示打印当前行。 (print
本身就意味着同一含义,所以我们可以写成那个。)您会注意到,awk程序中的字符串
li
周围包含斜杠(/)。 斜线表示li
是要搜索的模式。 这种类型的模式称为正则表达式,稍后将对其进行详细介绍(请参见Regular Expressions)。 允许该模式匹配单词的各个部分。 awk程序周围有单引号,因此shell不会将其中的任何字符解释为特殊的shell字符。
这是程序打印的内容:$ awk '/li/ { print $0 }' mail-list -| Amelia 555-5553 amelia.zodiacusque@gmail.com F -| Broderick 555-0542 broderick.aliquotiens@yahoo.com R -| Julie 555-6699 julie.perscrutabor@skeeve.com F -| Samuel 555-3430 samuel.lanceolis@shu.edu A
-
在awk规则中,可以省略模式或动作,但不能两者都省略。如果省略该模式,则对每个输入行执行该动作。如果省略该动作,则默认动作是打印与该模式匹配的所有行。因此,我们可以省略上一个示例中的操作(打印语句和花括号),结果将是相同的:awk打印所有与模式
li
匹配的行。相比之下,省略打印语句但保留花括号将执行一个不执行任何操作的空操作(即,不打印任何行)。许多实用的awk程序只有一两行。以下是一些有用的简短程序,可以帮助您入门。其中一些程序包含尚未涵盖的构造。以下大多示例都使用名为data的数据文件,这只是一个占位符;在自己的文件中需要替换为自己的文件名:-
打印每行超过80个字符的行:
awk 'length($0) > 80' data
在单一的规则将关系表达式作为其模式,并且不执行任何操作,因此它使用默认操作来打印记录。
-
打印最长输入行的长度:
awk '{ if (length($0) > max) max = length($0) } END { print max }' data
与END关联的代码在所有输入被读取后执行;it’s the other side of the coin to BEGIN.
-
打印data中最长行的长度:
expand data | awk '{ if (x < length($0)) x = length($0) } END { print "maximum line length is " x }'
此示例与上一个示例稍有不同:输入是由expand实用程序处理的,将TAB更改为空格,因此,比较的宽度实际上是右边距列,而不是每行输入字符的数量。
-
打印至少包含一个字段的每一行:
awk 'NF > 0' data
这是从文件中删除空白行的简便方法(或者,类似于旧文件创建一个新文件,但空白行已从中删除)。
-
打印从0到100的七个随机数,包括100在内:
awk 'BEGIN { for (i = 1; i <= 7; i++) print int(101 * rand()) }'
-
打印
files
使用的总字节数:ls -l files | awk '{ x += $5 } END { print "total bytes: " x }'
-
打印文件使用的千字节总数:
ls -l files | awk '{ x += $5 } END { print "total K-bytes:", x / 1024 }'
-
打印所有用户的登录名的排序列表:
awk -F: '{ print $1 }' /etc/passwd | sort
-
计算文件中的行数:
awk 'END { print NR }' data
-
打印data文件中的偶数行:
awk 'NR % 2 == 0' data
如果改用表达式
NR%2 == 1
,则程序将打印奇数行
-
两个规则的例子
-
awk实用程序一次只读取一行输入文件。 对于每一行,awk都会尝试每个规则的模式。 如果多个模式匹配,则几个动作将按照它们在awk程序中出现的顺序执行。 如果没有任何模式匹配,则不会执行任何操作。
-
在处理了所有与该行匹配的规则(也许没有规则)之后,awk读取下一行。 (但是,请参阅The next Statement部分,另请参见The nextfile Statement部分。)这将一直持续到程序到达文件末尾为止。 例如,以下awk程序包含两个规则:
/12/ { print $0 } /21/ { print $0 }
第一条规则将字符串
12
作为模式,将print $ 0
作为动作。 第二个规则以字符串21
作为模式,还以print $ 0
作为动作。 每个规则的动作都包含在其自己的大括号内。该程序将打印包含字符串
12
或字符串21
的每一行。 如果一行包含两个字符串,则将其打印两次,每条规则打印一次。如果我们在两个示例数据文件(mail-list和inventory-shipped)上运行此程序,则会发生这种情况:
$ awk '/12/ { print $0 } > /21/ { print $0 }' mail-list inventory-shipped -| Anthony 555-3412 anthony.asserturo@hotmail.com A -| Camilla 555-2912 camilla.infusarum@skynet.be R -| Fabius 555-1234 fabius.undevicesimus@ucb.edu F -| Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R -| Jean-Paul 555-2127 jeanpaul.campanorum@nyu.edu R -| Jan 21 36 64 620 -| Apr 21 70 74 514
请注意,mail-list中以 Jean-Paul开头的行是如何打印两次的,每个规则一次。(开始时是匹配模式
21
,然后是匹配模式12
)
一个更复杂的例子
-
现在,我们已经掌握了一些简单的任务,让我们看一下典型的awk程序可以做什么。 本示例说明了如何使用awk汇总,选择和重新排列另一个实用程序的输出。 它使用的功能尚未涵盖,因此,如果您不了解所有详细信息,请不要担心:
ls -l | awk '$6 == "Nov" { sum += $5 } END { print sum }'
此命令显示当前目录中所有文件的最后修改于11月(每年)的总字节数。 此示例的
ls -l
部分是系统命令,可提供目录中文件的列表,包括每个文件的大小和文件的最后修改日期。 其输出如下所示:-rw-r--r-- 1 arnold user 1933 Nov 7 13:05 Makefile -rw-r--r-- 1 arnold user 10809 Nov 7 13:03 awk.h -rw-r--r-- 1 arnold user 983 Apr 13 12:14 awk.tab.h -rw-r--r-- 1 arnold user 31869 Jun 15 12:20 awkgram.y -rw-r--r-- 1 arnold user 22414 Nov 7 13:03 awk1.c -rw-r--r-- 1 arnold user 37455 Nov 7 13:03 awk2.c -rw-r--r-- 1 arnold user 27511 Dec 9 13:07 awk3.c -rw-r--r-- 1 arnold user 7989 Nov 7 13:03 awk4.c
第一个字段包含读写权限,第二个字段包含文件的链接数,第三个字段标识文件的所有者。 第四个字段标识文件的组。 第五个字段包含文件的大小(以字节为单位)。 第六,第七和第八字段分别包含文件的最后修改日期,月份,日期和时间。 最后,第九个字段包含文件名。
在我们的awk程序中,
$ 6 ==“Nov”
是一个表达式,用于测试ls -l
的输出的第六个字段是否与字符串'Nov'
相匹配。 每当一行的第六个字段中包含字符串'Nov'
时,awk都会执行操作'sum + = $5'
。 这会将第五个字段(文件的大小)添加到变量sum
中。 结果,当awk完成读取所有输入行时,sum
是其行与模式匹配的文件大小的总和。 (这是有效的,因为awk变量会自动初始化为零。)处理完
ls
的最后一行输出后,将执行END
规则并打印sum
的值。 在此示例中,sum
的值为80600。这些更高级的awk技术将在后面的部分中介绍(请参阅Action一节)。 在继续进行更高级的awk编程之前,您必须知道awk如何解释您的输入并显示您的输出。 通过操作字段并使用打印语句,您可以生成一些非常有用且外观精美的报告。
awk语句与行
-
通常,awk程序中的每一行都是单独的语句或单独的规则,如下所示:
awk '/12/ { print $0 } /21/ { print $0 }' mail-list inventory-shipped
但是,gawk会忽略以下任何符号和关键字之后的换行符:
, { ? : || && do else
在任何其他位置的换行符都被视为语句的结尾。
如果您想在换行符将其终止的位置将单个语句分成两行,则可以通过在第一行以反斜杠字符(\)结束来继续执行该语句。 反斜杠必须是行上的最后一个字符,才能被识别为连续字符。 语句中的任何位置都可以使用反斜杠,后跟换行符,即使在字符串或正则表达式中间也是如此。 例如:
awk '/This regular expression is too long, so continue it\ on the next line/ { print $1 }'
在示例程序中,我们通常没有使用反斜杠继续。 gawk对行的长度没有限制,因此从不严格要求反斜杠连续; 它只是使程序更具可读性。 出于同样的原因,并且为了清楚起见,我们在整个Web页面上显示的程序中都保留了大多数语句。
当awk程序位于单独的源文件中而不是从命令行输入时,反斜杠连续最有用。 您还应该注意,许多awk实现都更具体地说明了在何处可以使用反斜杠连续。 例如,它们可能不允许您使用反斜杠分割连续字符串常量。 因此,为了最大程度地实现awk程序的可移植性,最好不要在正则表达式或字符串中间拆分行。
注意:反斜杠继续不能如C Shell中所述工作。 如果您使用的是POSIX-compliant shell,例如Unix Bourne shell或Bash,则它适用于文件中的awk程序和单发程序。 但是C Shell的行为有所不同! 在那里,您必须连续使用两个反斜杠,然后再使用换行符。 还要注意,使用C Shell时,awk程序中的每个换行符都必须以反斜杠转义。 为了显示:
% awk 'BEGIN { \ ? print \\ ? "hello, world" \ ? }' -| hello, world
在这里,
'%'
和'?'
是C shell的主要和辅助提示,类似于standard shell的'$'
和'>'
。将前面的示例与如何使用POSIX-compliant shell进行比较:
$ awk 'BEGIN { > print \ > "hello, world" > }' -| hello, world
awk是一种面向行的语言。 每个规则的动作必须与模式在同一行开始。 要在单独的行上包含模式和操作,必须使用反斜杠连续。 没有其他选择。
要记住的另一件事是反斜杠继续和注释不会混合。 一旦awk看到开始注释的
'#'
,它将忽略该行其余部分的所有内容。 例如:$ gawk 'BEGIN { print "dont panic" # a friendly \ > BEGIN rule > }' error→ gawk: cmd. line:2: BEGIN rule error→ gawk: cmd. line:2: ^ syntax error
在这种情况下,反斜杠似乎会将注释继续到下一行。 但是,反斜杠和换行符的组合从未被注意到,因为它被隐藏在注释中。 因此,BEGIN被标记为语法错误。
当一条规则中的awk语句很短时,您可能需要在一行中放置多个以上的语句。 这是通过用分号(
;
)分隔语句来完成的。 这也适用于规则本身。 因此,本节开始处显示的程序也可以这样编写:/12/ { print $0 } ; /21/ { print $0 }
注意:要求同一行上的规则必须用分号分隔的要求不是原始的awk语言; 添加它是为了与操作中的语句处理保持一致。
第一章总结:
- awk中的程序由模式-动作对组成。
- 没有模式的动作始终运行。 一个模式的默认动作(也即没有指定动作的情况下)是
'{print $ 0}'
。 - 使用
‘awk 'program' files’
或者‘awk -f program-file files’
来运行awk。 - 您可以使用特殊的
'#!'
标题行来创建可直接执行的awk程序。 - awk程序中的注释以
'#'
开头,并持续到同一行的末尾。 - 在作为较大的Shell脚本(或 MS-Windows batch file)的一部分编写awk程序时,请注意引用问题。
- 您可以使用反斜杠继续来继续源代码行。 在逗号,大括号,问号,冒号,
'||'
,'&&'
,'do'
或else
操作之后,行会自动继续。
第二章总结:
-
gawk从左到右解析命令行上的参数,以确定应将其视为选项还是非选项参数。
-
gawk可以识别几个控制其操作的选项,如Command-Line Options中所述。 所有选项均以
'-'
开头。 -
任何不能识别为选项的参数都将被视为非选项参数,即使该参数以
'-'
开头。- 但是,当一个选项本身需要一个参数,并且该选项在命令行上与该参数至少间隔一个空格时,该空格将被忽略,并且该参数被视为与该选项相关。 因此,在调用
'gawk -F x'
时,'x'
被视为属于-F
选项,而不是单独的非选项参数。
- 但是,当一个选项本身需要一个参数,并且该选项在命令行上与该参数至少间隔一个空格时,该空格将被忽略,并且该参数被视为与该选项相关。 因此,在调用
-
一旦gawk找到了非选项参数,它就会停止寻找选项。 因此,所有后面的参数也都是非选项参数,即使它们类似于公认的选项。
-
如果不存在
-e
或-f
选项,则gawk希望程序文本位于第一个非选项参数中。 -
除第一个非选项参数中提供的程序文本外,所有非选项参数都按照使用ARGC和ARGV中的说明放置在ARGV中,并按照其他命令行参数中的说明进行处理。 调整ARGC和ARGV会影响awk处理输入的方式。
-
所有awk版本的三个标准选项是
-f
,-F
和-v
。 gawk提供了这些以及许多其他选项,以及相应的GNU风格的长选项。 -
非选项命令行参数通常被视为文件名,除非它们的格式为
var = value
,在这种情况下,它们将被视为在处理输入时在该位置执行的变量赋值。 -
您可以使用一个减号(
'-'
)来指代命令行上的标准输入。 gawk还允许您使用特殊文件名/dev/stdin
。 -
gawk注意许多环境变量。 AWKPATH,AWKLIBPATH 和POSIXLY_CORRECT是最重要的。
-
gawk的退出状态会将信息传达给调用它的程序。 在awk程序中使用
exit
语句设置退出状态。 -
gawk允许您使用
@include
语句或-i
和-f
命令行选项将其他awk源文件包含到程序中。 -
gawk允许您使用
@load
语句或-l
选项加载用C或C ++编写的其他函数。 (此高级功能将在后面的“编写gawk的扩展”中进行介绍。)
这部分就先到这里啦!另外,正则表达式部分还需要详看,就记在下一篇把!