awk 匹配_linux三剑客之awk

awk(三位作者的名字命名):文本分析工具,Linux及unix环境中功能强大的数据处理工具之一。

相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大。

简单来说awk就是把文件逐行的读入,默认以空格为分隔符将每行切片,切开的部分再进行各种分析处理。

awk的特点:使用直译器(Interpreter)不需先行编译; 变量无类型之分(Typeless), 可使用文字当数组的下标(Associative Array)...等特色. 因此, 使用awk撰写程序比起使用其它语言更简洁便利且节省时间. awk还具有一些内建功能, 使得awk擅于处理数据行(Record), 字段(Field)型态的资料; 此外, awk内建有pipe的功能, 可将处理中的数据传送给外部的 Shell命令加以处理, 再将Shell命令处理后的数据传回awk程序, 这个特点也使得awk程序很容易使用系统资源.

命令语法格式:

awk '{pattern + action}' 或者 awk 'pattern {action}'

awk程序的主要结构:

awk程序中主要语法是 Pattern { Actions}, 故常见之awk 程序其型态如下 :

Pattern1 { Actions1 }

Pattern2 { Actions2 }

......

PatterN{ ActionsN }

pattern:可接受不同形态的Pattern.一般使用关系表达式来当成pattern.

如:>,<,>=,<-,==,!= 等关系运算符。

此外,awk还提供~(match)及!~(not match)两个关系运算符:如 A ~ B 表示字符串A中是否包含B表达式的子字符串。english ~ /en/

actions:

Actions 是由许多awk指令构成. 而awk的指令与 C 语言中的指令十分类似.

awk的 I/O指令 : print, printf( ), getline...

awk的 流程控制指令 : if(...){..} else{..}, while(...){...},for(..,..,..){...},do{...}while(..)

例如:awk 'BEGIN{a="helloword";if(a~/hello/){print "ok"}}'

e81b93ef706937557b063a0b925627b4.png

echo | awk 'BEGIN{a="helloworld"}a~/hello/{print "0k"}';//此语法分成两个pattern+action模式;1.BEGIN{a="2222helloworld"};2.a~/222/{print "ok"}; 使用echo 的原因 awk往往后面匹配相关的文件,按行号进行读取,取消echo | 第二个匹配模式不会执行,会等待输入行信息,echo | 会把空内容重定向到awk中(即模拟文件读取)直接运行第二个pattern+action

awk的字段含义:

$0: 内容为awk读入的数据行的数据

$1: 每行切片的第一个字段的数据

$2: 每行切片的第二个字段的数据

...以此类推

awk工作流程:

当awk从数据文件中读取一个数据行时, awk会使用内建变量$0予以记录.每当$0被改动时(例如 : 读入新的数据行 或 自行变更 $0,...)awk 会立刻重新分析$0的字段情况, 并将$0上各字段的数据用$1, $2, ..予以记录.若数据文件中还有未读取的数据,则继续执行下一行。

awk内置变量:

ARGC:命令行参数个数

af759c3dfd015f157627f8c087505d9c.png

ARGV:命令行参数排列(基于索引下标获取ARGC参数的值)

39e4b96244f6aaf136c9234f648d3a75.png

ENVIRON:支持队列中系统环境变量的使用

be334eb9fbb71c0a28a5085fc2318e94.png

FILENAME:awk浏览的文件名

3d220d39a65b8930ea3b0a0fb90d6e0a.png

FNR:浏览文件的记录数

7f4006b31b55176e26baa673083039a0.png

FS(fields separator):设置输入域分割符,等价于命令行-F选项

c5e7d4ae151d568bb43f1760f574286a.png

NF(number of fields):浏览记录的域的个数

e45cfee4ecbee5c4a49b673e0713271c.png

NR(number of rows) :已读的记录数

a2663130d7dc002a402a83d112d4aaa7.png

OFS:输出域分割符

91dcadd1f5f4766962cb34eac93301ab.png

ORF:输出记录分割符

f91c82f04df6afb550fc4a03c39b2c59.png

RS:控制记录分割符

0115628413fad14a6215afb0b1f0f762.png

注:所谓的域即表示字段,所谓的记录即表示行

awk中的数组:

awk程序中允许使用字符串当做数组的下标(index).

使用字符串当数组的下标(index).

使用数组前不必声明数组名及其大小.

81b24d73b5779a47a1fea84faf30c665.png

awk语法:

1.命令行模式:

awk 'BEGIN{a="helloword";if(a~/hello/){print "ok"}}'

echo | awk 'BEGIN{a="helloworld"}a~/hello/{print "0k"}';

2.文本模式:

awk -f awk程序文件名 数据文件名

如:

251f47593d6c67ee5a0df392f4dae36b.png

7af62a7afe4250ed250f7e43ce473ebd.png

awk -f awk主程序文件名 -f awk函数文件名 数据文件文件名

70d8c74fd3fc5cc2672ea2c748be4b2e.png

9a4b13c816675e13af284bb96efc81e5.png

30bd7d2cbc304a80ad40edc0cf13f047.png

awk的使用:

1.awk 程序中使用Shell命令:

awk程序中允许呼叫Shell指令. 并提供管道解决awk与系统间数据传递的问题. 所以awk很容易使用系统资源.

如:打印在线人数。

3e82670fc99ec478456109ec14f94354.png

91a2f0259d9b70e7088ed3948a097941.png

awk 'BEGIN{while("who"|getline){n++} print n}'打印在线人数。"|" 为 awk 中表示管道的符号. awk 把 | 之前的字符串"who"当成Shell上的命令, 并将该命令送往Shell执行, 执行的结果(原先应于屏幕印出者)则藉由pipe送进awk程序中.

getline var < file所指定的 file变量 var(var省略时,表示置于$0)

getline varpipe 变量变量 var(var省略时,表示置于$0)

getline var见 注一变量 var(var省略时,表示置于$0)

2.重定向输出到文件:

awk中任何输出函数之后皆可借助使用与UNIX 中类似的 I/O 重定向符, 将输出的数据重定向到指定的文件; 其符号仍为 > (输出到一个新产生的文件) 或 >> ( 添加输出的数据到文件末尾 ).

9eb2a93a13b2438788a993af863e6ff1.png

8bff34043c90d3074837f31f9a074e26.png

注:awk程序中, 文件名称 hello.txt 的前后须以" (双引号)括住, 表示 hello.txt 为一字符串常量. 若未以"括住, 则hello.txt将被awk解释为一个变量名称.在awk中任何变量使用之前, 不必事先声明. 其初始值为空字符串(Null string) 或 0.因此程序中若未以 " 将 hello.txt 括住, 则 hello.txt 将是一变量, 其值将是空字符串, 这会在执行时造成错误(Unix 无法帮您开启一个以空字符串为文件名的文件).

3.awk中如何利用系统资源:

awk程序中很容易使用系统资源. 这包括在程序中途调用 Shell 命令来处理程序中的部分数据; 或在调用 Shell 命令后将其产生的结果交回 awk 程序(不需将结果暂存于某个文件). 这一过程是借助 awk 所提供的管道 (虽然有些类似 Unix 中的管道, 但特性有些不同),及一个从 awk 中呼叫 Unix 的 Shell 命令的语法来达成的.

awk 提供与 UNIX 用法近似的 pipe, 其记号亦为 "|". 其用法及含意如下 :

awk程序中可接受下列两种语法:

[a. 语法] awk output 指令 | "Shell 接受的命令"

3528e62826ce1ce28a27e400d6cb9ec6.png

[b. 语法] "Shell 接受的命令" | awk input 指令

( 如 : "ls " | getline)

7d5047bd0df129d333ef07215f6be640.png

注 : awk input 指令只有 getline 一个.

awk output 指令有 print, printf() 二个.

在a 语法中, awk所输出的数据将转送往 Shell , 由 Shell 的命令进行处理.以上例而言, print 所输出的数据将经由 Shell 命令 "sort -k 1" 排序后再送往屏幕(stdout).

上列awk程序中, "print$1, $2" 可能反复执行很多次, 其输出的结果将先暂存于 pipe 中,等到该程序结束时, 才会一并进行 "sort -k 1".

须注意二点 : 不论 print $1, $2 被执行几次, "sort -k 1" 的执行时间是 "awk程序结束时",

"sort -k 1" 的执行次数是 "一次".

在 b 语法中, awk将先调用 Shell 命令. 其执行结果将通过 pipe 送入awk程序,以上例而言, awk先让 Shell 执行 "ls",Shell 执行后将结果存于 pipe, awk指令 getline再从 pipe 中读取数据.

使用本语法时应留心: 以上例而言,awk "立刻"调用 Shell 来执行 "ls", 执行次数是一次.

getline 则可能执行多次(若pipe中存在多行数据).

除上列 a, b 两种语法外, awk程序中其它地方如出现像 "date", "cls", "ls"... 这样的字符串, awk只把它当成一般字符串处理.

awk程序由三个主要部分构成 :

[ i.] Pattern { Action} 指令

[ ii.] 函数主体. 例如 : function double( x ){ return 2*x }

[ iii.] Comment ( 以 # 开头识别之)

awk 的输入指令 getline, 每次读取一列数据. 若getline之后

未接任何变量, 则所读入之资料将以$0 记录, 否则以所指定的变量储存之.

4. awk提供另一个调用Shell命令的方法, 即使用awk函数system("shell命令")

de0bc9280a4ac35fa4178cb889a9a5a0.png

但使用 system( "shell 命令" ) 时, awk无法直接将执行中的部分数据输出给Shell 命令. 且 Shell 命令执行的结果也无法直接输入到awk中.

5.执行awk程序的几种方式

本小节中描述如何将awk程序直接写在 shell script 之中. 此后使用者执行 awk 程序时, 就不需要每次都键入 " awk -f awk程序文件 数据文件" .

script 中还可包含其它 Shell 命令, 如此更可增加执行过程的自动化.

建立一个简单的 awk程序 hello.awk, 如下:

608e458db096e3565ecdc4ffc9b72538.png

50538cd86e805f2009ac23837ba07210.png

这个程序执行时会把数据文件的内容 print 到屏幕上( 与cat功用类似 ).

print 之后未接任何参数时, 表示 "print $0".

若欲执行该awk程序, 来印出文件 staff.txt及 ret.txt 的内容时,

必须于 UNIX 的命令行上执行下列命令 :

方式一 awk -f mydump.awk statt.txt ret.txt

方式二 awk '{print}' statt.txt ret.txt第二种方式系将awk 程序直接写在 Shell 的命令行上, 这种方式仅适合较短的awk程序.

方式三 建立如下之 shell script, 并取名为 awk.sh,

#!/bin/sh

# 注意以下的 awk 与 ' 之间须有空白隔开

awk '

{print}

' $*

# 注意以上的 ' 与 $* 之间须有空白隔开

执行 awk.sh 之前, 须先将它改成可执行的文件(此步骤往后不再赘述). 请执行如下命令:

$ chmod +x awk.sh

往后使用者就可直接把 awk.sh 当成指令, 来display任何文件.

例如 :

6d4c7748ee2e9bf64fbae323d928a490.png

[ 说 明 : ]

在script文件 awk.sh 中, 指令"awk"与第一个 ' 之间须有空格(Shell中并无" awk' "指令).

第一个 ' 用以通知 Shell 其后为awk程序.

第二个 ' 则表示 awk 程序结束.

故awk程序中一律以"括住字符串或字符, 而不使用 ' , 以免Shell混淆.

$* 为 shell script中的用法, 它可用来代表命令行上 "awk.sh之后的所有参数".

例如执行 :

$ ./asw.sh staff.txt ret.txt

事实上 Shell 已先把该指令转换成 :

awk '

{ print}

' staff.txt ret.txt

本例中, $* 用以代表 "staff.txt ret.txt". 在Shell的语法中, 可用 $1 代表第一个参数, $2 代表第二个参数. 当不确定命令行上的参数个数时, 可使用 $* 表之.

awk命令行上可同时指定多个数据文件.

以awk -f hello.awk staff.txt ret.txt为例,awk会先处理staff.txt, 再处理 ret.txt. 此时若文件无法打开, 将造成错误.

例如: 不存在文件"file_no_exist", 则执行

$ awk -f hello.awk file_no_exit

将产生运行时错误(无法打开文件).

但某些awk程序 "仅" 包含以 BEGIN 为Pattern的指令. 执行这种awk程序时, awk并不须开启任何数据文件.此时命令行上若指定一个不存在的数据文件,并不会产生 "无法打开文件"的错误.(事实上awk并未打开该文件)

例如执行:

$ awk 'BEGIN {print "Hello,World!!"} ' file_no_exist

该程序中仅包含以 BEGIN 为 Pattern 的 Pattern {actions}, awk 执行时并不会开启任何数据文件; 所以不会因不存在文件file_no_exit而产生 " 无法打开文件"的错误.

awk会将 Shell 命令行上awk程序(或 -f 程序文件名)之后的所有字符串, 视为将输入awk进行处理的数据文件文件名.

若执行awk的命令行上 "未指定任何数据文件文件名", 则将stdin视为输入之数据来源, 直到输入end of file( Ctrl-D )为止.

读者可以用下列程序自行测试, 执行如下命令 :

$ awk -f hello.awk #(未接任何数据文件文件名)

$ ./awk.sh #(未接任何数据文件文件名)

将会发现: 此后键入的任何数据将逐行复印一份于屏幕上. 这情况不是机器当机 ! 是因为awk程序正处于执行中. 它正按程序指示, 将读取数据并重新dump一次; 只因执行时未指定数据文件文件名, 故awk 便以stdin(键盘上的输入)为数据来源. 读者可利用这个特点, 设计可与awk即时聊天的程序.

6.自定义函数的使用

awk不仅能自动分割字段, 也允许使用者改变其字段切割方式以适应各种格式之需要. 使用者也可自定义函数, 若有需要可将该函数单独写成一个文件,以供其它awk程序调用.

3721521938e2656604555c4c124b7a1a.png

7.使用getline来读取数据

c4ca350d4edd1be0d3230fd00d790011.png

8e1a43edfd0545c3b2121dde46b8b851.png

8. 如何读取命令行上的参数

大部分的应用程序都允许使用者在命令之后增加一些选择性的参数,执行awk时这些参数大部分用于指定数据文件文件名,有时希望在程序中能从命令行上得到一些其它用途的数据. 本小节中将叙述如何在awk程序中取用这些参数.

e00e8f19b1ec608183271c0f747e04ee.png

ARGC : 为一整数. 代表命令行上, 除了选项-v, -f 及其对应的参数之外所有参数的数目.

ARGV[ ] : 为一字符串数组. ARGV[0],ARGV[1],...ARGV[ARGC-1].

分别代表命令行上相对应的参数.

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值