前言
年前杂事比较多一些,特别涉及到对一些日志文本的分析,早就知道awk是这方面处理的神器,在写恶心的php间隙学习一下,虽然我觉得自己的php写的非常规范了,但是那种哦敢调用api、调用扩展的方式还是让我觉得恶心,虽然很方便,话不多说,开始awk学习,可能会分阶段完成这篇文章,有时间就记录一些吧
awk程序设计模型
awk程序是由所谓的主输入(main input)循环组成的。一个循环是一个例程,它将一直重复执行直到有一些存在的条件终止它。你不必写这个循环,它是现成的,它作为一个框架存在,在这个框架中编写的代码能够执行。
主输入循环执行的行数和输入的行数相同。
awk允许你编写两个特殊的例程,他们在任何输入被读取前和所有输入被读取后执行。他们是BEGIN和END规则相关的过程。换句话说,在主输入循环前和主输入循环之后你可以做一些处理。
awk脚本可以分为3个部分:
- 处理输入前的将做的处理
- 处理输入过程中将做的处理
- 处理输入完成后做的处理
awk工作流程:
- 自动从指定的数据文件中读取一个数据行
- 自动更新相关的内建变量之值。如:NF,NR,$0,$1,..
- 依次执行程序中所有的Pattern{Actions}指令。
- 当执行完程序中所有Pattern{Actions}时,若数据文件中还有未读取的数据,则反复执行上述步骤(awk的程序设计模型决定)
执行awk
awk 'awk程序' 处理文件名
处理文件中包含多少行,awk程序就执行多少次,这是由awk程序设计模型决定的!(
ps:处理文件为空,则awk不执行,很多初学者测试时容易犯这种错误,比如我)
awk程序的主要结构
awk程序中主要语法是Pattern{Actions},故而常见的awk程序其型态如下:
Pattern1 {Actions1}
Pattern2 {Actions2}
...
Pattern3 {Actions3}
Pattern
awk可以接受许多不同型态的Pattern.一般常使用“关系表达式(Relational expression)”来当成Pattern。
例如:
x > 65是一个Pattern,判断变量x与65的大小关系
awk提供C语言中常见的关系运算符(Relational Operators)如:
>,<,==,>=,<=,!=
此外,awk还提供了~(match)及 !~(not match)二个关系运算符
Actions
Actions是由许多awk指令构成,而awk的指令与c语言中的指令十分类似
例如:
awk的I/O指令:print,printf(),getline...
awk的流程控制指令:if(...){...}else{...},while(...){...}
awk处理Pattern{Actions}
awk会先判断该Pattern的值,若为true,则awk执行Pattern所对应的Actions。反之,若Pattern值部为true,则awk将不执行该Pattern所对应的Actions。
例如:
awk '90 > 78 {printf "hello world!\n"}' test.txt
如果test.txt不为空,肯定可以输出hello world!
awk ' 1 > 2 {printf "hello world\n"}' test.txt
就算test.txt不为空,由于Pattern 1 > 2的值为false,所以printf语句一定不会执行!
awk处理{Actions}(缺少Pattern部分)
有时语法Pattern{Actions}中,Pattern部分被省略,只剩{Actions}。这种情况下表示:awk无条件执行这个Actions
awk内建字段变量
字段变量 |
字段含义 |
$0 |
当前awk所读入行的内容 |
$1 |
$0上分隔符分割后第一个字段的内容 |
$2 |
$0上分隔符分割后第二个字段的内容 |
... |
以此类推 |
NF(number of Fields) |
$0上的字段数目 |
NR(NUMBER OF RECORDS) |
awk已读入的数据行的数目 |
打印文件中指定字段数据
文件内容
wangzhengyi 24 linux c php cuc
chenshan 24 linux php emacs cuc
bululu 26 english computer electricity cuc
按照制定格式输出
awk中提供了与c语言类似的printf()函数,可以用这个函数控制格式输出,我强烈推荐printf(恶心的echo真的快让我受够了,我喜欢一切跟c相关的东西)
awk '{printf("name is %s,age is %d,technology has %s %s %s,study in %s\n",$1,$2,$3,$4,$5,$6)}' test
结果:
name is wangzhengyi,age is 24,technology has linux c php,study in cuc
name is chenshan,age is 24,technology has linux php emacs,study in cuc
name is bululu,age is 26,technology has english computer electricity,study in cuc
awk的流程控制语句
常见错误:
初学者开始使用流程控制语句时,都喜欢采用类似于c代码的风格,但是可能会碰到这个错误:
awk: line 1: syntax error at or near if
举例:
(1)错误代码
awk -F "^A" 'if(2 > 3) {printf("%s %d\n", $1, $2)}' test
(2)正确的类C的代码应该
awk -F "^A" '{if(2 > 3) {printf("%s %d\n", $1, $2)}}' test
注意:正确的类c风格应该多了一个括号的包围
条件判断语句(if)
格式
{
if(表达式)
{
语句一;
.......;
}else if(表达式)
{
语句2;
........
}else
{
语句3;
........
}
}
测试代码
循环语句(while,for)
while格式
{
while(表达式)
{
语句;
}
}
for格式
{
for(变量初始化; 条件; 表达式)
{
语句;
}
}
{
for(变量 in 数组)
{
语句;
}
}
测试代码:
awk数组
如果写过php和shell,那对awk的数组一定不会陌生,就是awk的数组既支持下标数组,也支持关联数组.
写个测试awk数组的用例,大家看一下就好了:
awk模式匹配
awk提供了两个运算符~(match)与!~(not match),这两个模式匹配都是正则表达式的应用,注意其使用的语法即可
语法规则
若A为一字符串,B为一正则表达式
A~B 判断字符串A中是否包含能匹配B式样的子字符串
A!~B 判断字符串A中是否未包含能匹配B式样的子字符串
测试用例
$0 ~ /[0-9]*/ 这是判断每行是否包含数字的最基础的正则表达式,如果这个不懂的话建议去看正则表达式基础吧