linux高级原7

来源:互联网 发布:matlab支持c语言吗 编辑:程序博客网 时间:2024/06/09 07:23

使用awk 进行高级文本处理

灵活性是awk最大的优势。

awk脚本的结构基本如下所示:
awk ' BEGIN{ print "start" } pattern { commands } END{ print "end" } 'file
awk命令也可以从stdin中读取。
awk脚本通常由3部分组成。BEGIN,END和带模式匹配选项的常见语句块。这3个部分都是可选项,在脚本中可省略任意部分。

以下awk脚本被包含在单引号或双引号之间:
awk 'BEGIN { statements } { statements } END { end statements }'
也可以使用:
awk "BEGIN { statements } { statements } END { end statements }"
例如:
$ awk 'BEGIN { i=0 } { i++ } END{ print i}' filename

或者
$ awk "BEGIN { i=0 } { i++ } END{ print i }" filename

awk命令的工作方式如下所注。
(1) 执行BEGIN { commands } 语句块中的语句。
(2) 从文件或stdin中读取一行,然后执行pattern { commands }。重复这个过程,直到
文件全部被读取完毕。
(3) 当读至输入流末尾时,执行END { commands } 语句块。
BEGIN语句块在awk开始从输入流中读取行之前被执行。这是一个可选的语句块,诸如变量
初始化、打印输出表格的表头等语句通常都可以写入BEGIN语句块中。
END语句块和BEGIN语句块类似。END语句块在awk从输入流中读取完所有的行之后即被执
行。像打印所有行的分析结果这类汇总信息,都是在END语句块中实现的常见任务(例如,在比
较过所有的行之后,打印出最大数)。它也是一个可选的语句块。
最重要的部分就是pattern语句块中的通用命令。这个语句块同样是可选的。如果不提供该语句块,则默认执行{ print },即打印所读取到的每一行。awk对于每一行,都会执行这个语句块。这就像一个用来读取行的while循环,在循环体中提供了相应的语句。
每读取一行,awk就会检查该行和提供的样式是否匹配。样式本身可以是正则表达式、条件语句以及行匹配范围等。如果当前行匹配该样式,则执行{ }中的语句。
样式是可选的。如果没有提供样式,那么awk就认为所有的行都是匹配的,并执行{ }中的语句。
让我们看看下面的例子:
$ echo -e "line1\nline2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" } '
Start
line1
line2
End
当使用不带参数的print时,它会打印出当前行。关于print,需要记住两件重要的事情:
当print的参数是以逗号进行分隔时,参数打印时则以空格作为定界符。在awk的print语句中,双引号是被当做拼接操作符(concatenation operator)使用的。

{ }类似于一个循环体,会对文件中的每一行进行迭代。

awk命令具有丰富的特性。要想洞悉awk编程的精妙之处,首先应该熟悉awk重要的选项和功
能。让我们来看看awk的一些重要功能。
1. 特殊变量
以下是可以用于awk的一些特殊变量。
 NR:表示记录数量,在执行过程中对应于当前行号。
 NF:表示字段数量,在执行过程中对应于当前行的字段数。
 $0:这个变量包含执行过程中当前行的文本内容。
 $1:这个变量包含第一个字段的文本内容。
 $2:这个变量包含第二个字段的文本内容。
例如:
$ echo -e "line1 f2 f3\nline2 f4 f5\nline3 f6 f7" | \

awk '{
print "Line no:"NR",No of fields:"NF, "$0="$0, "$1="$1,"$2="$2,"$3="$3
}'
Line no:1,No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
Line no:2,No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
Line no:3,No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7


3. 用getline读取行
awk通常默认读取一个文件的所有行。如果只想读取某一行,可以使用getline函数。有时
候,我们需要从BEGIN语句块中读取第一行。
语法:getline var。变量var就包含了特定行的内容。如果调用不带参数的getline,我
们可以用 $0、$1和$2访问文本行的内容。
例如:
$ seq 5 | awk 'BEGIN { getline; print "Read ahead first line", $0 } { print $0 }'
Read ahead first line 1
2
3
4
5


4. 使用过滤模式对awk处理的行进行过滤
我们可以为需要处理的行指定一些条件,例如:
$ awk 'NR < 5' # 行号小于5的行
$ awk 'NR==1,NR==4' # 行号在1到5之间的行
$ awk '/linux/' # 包含样式linux的行(可以用正则表达式来指定模式)
$ awk '!/linux/' # 不包含包含模式为linux的行

5. 设置字段定界符
默认的字段定界符是空格。我们也可以用 -F "delimiter"明确指定一个定界符:
$ awk -F: '{ print $NF }' /etc/passwd
或者
awk 'BEGIN { FS=":" } { print $NF }' /etc/passwd

6. 从awk中读取命令输出
在下面的代码中,echo会生成一个空白行。变量cmdout包含命令grep root /etc/passwd
的输出,该命令会打印出包含root的行。
将命令的输出结果读入变量output的语法如下:
"command" | getline output ;
例如:
$ echo | awk '{ "grep root /etc/passwd" | getline cmdout ; print cmdout }'
root:x:0:0:root:/root:/bin/bash
通过使用getline,我们将外部shell命令的输出读入变量cmdout。


7. 在awk中使用循环
在awk中可以使用for循环,其格式如下:
for(i=0;i<10;i++) { print $i ; }
或者
for(i in array) { print array[i]; }
8. awk内建的字符串控制函数
awk有很多内建的字符串控制函数,让我们认识一下其中部分函数。
 length(string):返回字符串的长度。
 index(string, search_string):返回search_string在字符串中出现的位置。
 split(string, array, delimiter):用定界符生成一个字符串列表,并将该列表存
入数组。
 substr(string, start-position, end-position):在字符串中用字符起止偏移
量生成子串,并返回该子串。
 sub(regex, replacement_str, string):将正则表达式匹配到的第一处内容替换
成replacment_str。
 gsub(regex, replacment_str, string):和sub()类似。不过该函数会替换正则表
达式匹配到的所有内容。
 match(regex, string):检查正则表达式是否能够匹配字符串。如果能够匹配,返回
非0值;否则,返回0。match()有两个相关的特殊变量,分别是RSTART和RLENGTH。变量RSTART包含正则表达式所匹配内容的起始位置,而变量RLENGTH包含正则表达式所匹配内容的长度。



0 0
原创粉丝点击