认识awk
Awk是一种小巧的编程语言及命令行工具。它非常适合服务器上的日志处理,主要是因为Awk可以对文件进行操作。它同样使你能够处理数据并转换数
据。
gawk是最新的版本,使用它可以做到数据查找,抽取文本中的数据,创建管道流。
awk有一个主输入循环,次循环反复执行,直到终止条件被触发。我们写好的代码被嵌入到朱输入循环框架中执行。
BEGIN在主输入循环之前执行(未读取输入文件行之前),END则是在主输入循环之后执行。
即AWK程序的三层结构:
BEGIN
主循环
END
代码结构:
Awk脚本的代码结构很简单,就是一系列的模式(pattern)和行为(action):
# comment
Pattern1 { ACTIONS; }
pattern决定了何时触发事件,action代表处理的方法。
我的第一份awk程序:
#!/bin/awk -f
#check all lines has 'I' header.
/^I/ { print }
/*
$ cat doc
I love linux
hello world
I enjoy it.
hahahaha.
$ ./I.awk doc
I love linux
I enjoy it.
*/
awk将每一个输入文件定义为记录,行中的每一个字符串定义为域,域之间的空格、tab键、其他符号叫做分隔符。
假设有多个tab,可以使用下列指令将其当做一个分隔符:
FS="\t+"
(FS="\t"
是单个的分隔符)
数据类型
Awk仅有两个主要的数据类型:字符串和数字。
即便如此,Awk的字符串和数字还可以相互转换。字符串能够被解释为数字并把它的值转换为数字值。
如果字符串不包含数字,它就被转换为0.
Awk有数组类型,并且它们是动态的一维关联数组。它们的语法是这样的:var[key] = value
。Awk可以模拟多维数组
awk中还有javascript特性的"23" == 23
awk的部分系统变量:
变量名 | 意义 |
---|---|
$0 | 所有的域 |
$n | 第n个域 |
ARGC | 命令行参数的数量 |
ARGV | 命令行参数数组 |
ARCIND | 命令行当前文件的位置 |
CONVFMT | 数字转换格式 |
ENVIRON | 环境变量关联数组 |
ERRNO | 最后一个系统错误的描述 |
FIELDWIDTHS | 字段宽度列表,空格键分隔 |
FILENAME | 当前文件名 |
FNR | 浏览文件记录数 |
NR | 当前记录数 |
FS | 字段分隔符 |
NF | 当前记录中的域数量 |
OFMT | 数字的输出格式 |
OFS | 输出域分隔符 |
ORS | 输出记录分隔符 |
RS | 记录分隔符 |
RLENGTH | 由match函数所匹配的字符串长度 |
awk printf修饰符:
修饰符 | 意义 |
---|---|
- | 左对齐 |
width | 域的步长 |
.prec | 小数点右边位数 |
awk的命令行参数不能被BEGIN{}字段访问。
换一句话说,传参往往和文件联系在一起。
#!/usr/bin/awk -f
{
i=0;
while(i < MAX){
print i++;
}
}
$ cat > read
I lll
$ ./arg.sh MAX=5 read
0
1
2
3
4
awk练习
怎样用shell+awk脚本实现查找/etc/passwd中所有uid>500的记录?
awk 'BEGIN {FS=":"} { if($3>500) print $0; }' red
查看/etc/passwd中所有和root相关的记录
#!/bin/bash
#ls all info about root
#下面的~表示模糊匹配。
awk 'BEGIN { FS=":"} $0~/root/ ' /etc/passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
查看一个文件中所有的空行,并打印行号。
cat -An doc
1 I love linux$
2 hello world$
3 I enjoy it.$
4 $
5 hahahaha.$
6 $
7 I am excited.$
8 $
9 hahaha.$
10 $
11 $
12 $
$ ./black_line.sh
4
6
8
12
all black has 4 lines.
$ cat black_line.sh
#!/bin/bash
#output all black line numbers and counts.
awk 'BEGIN{ x=0;
black=0;
}
{
x++;
#if($1==""){
if(/^$/){
black++;
print x;
}
} END{
printf("all black has %d lines.\n",black);
}' doc
将不是以“---->”
开头的行打印出来,并重定向一个文件中。
awk '!/^---->/{ print $0 > "read_awk" }' read.txt
计算sin(0),cos(0),log(1),exp(1),sqrt(2). 保留4位小数。
$ cat calcu.sh
#!/bin/bash
awk '
BEGIN{ OFMT="%.4f";
gsin = sin(0);
gcos = cos(0);
glog = log(1);
gexp = exp(1);
gsqrt = sqrt(2);
print gsin,gcos,glog,gexp,gsqrt;
}
'
./calcu.sh
0 1 0 2.7183 1.4142
产生1000内的随机数
#!/bin/bash
awk '
BEGIN{
srand(); #默认用时间作为种子
ans = int(rand()*1000+0.5);
print ans;
}
'
分割字符串。
awk 'BEGIN{
info="I love linux and shell.";
split(info,elements," ");
len=0;
for(i in elements){
print i,elements[i];
len++;
}
printf("length of array is %d.\n",len);
}
'
$ ./split.sh
1 I
2 love
3 linux
4 and
5 shell.
length of array is 5.
$ cat split.sh
打印每一行的文字
awk '
BEGIN{
while(getline < "jordan"){
count++;
print $0;
}
printf("the number of Lines is %d\n",count);
close("jordan");
}'
在下列文本中寻找每一行中“乔丹”第一次出现的位置
这是 乔丹 在 NBA 季 后 赛 当中 的 第一 记 伟大 绝 杀。 在这之前, 乔丹 也 绝 杀 过, 却 没有 任何 一个 如此 关键, 如此 致命, 如此 影响 深远, 如此 让人 刻骨铭心。 这 记 绝 杀 中 投, 在 NBA 史册 中有 个 专属 的 脆生 生的 名字, 就叫“ The Shot”( 那一 投)。
这场 生 死战, 乔丹 得到 44 分, 抢 9 个 篮板, 助攻 6 次。 最后 那 两分, 弥补 了 两天 前 第四 场 绝 杀 未成 和 罚球 不进 的 过失。 乔丹 说:“ 这大 概 是我 在 NBA 投进 的 最重要的 一个 球。 主要 是因为, 我 在 紧要 关头, 证明了 自己 是 可信 的。 我 认为 我们 可以 击败 他们, 但是 星期五, 我 错失 了 最后 的 罚球 和 最后 一 投, 害 我们 输 了, 那 是我 在 篮球 场上 最 低落 的 时刻。 就好像 我 高中 时 没 进 得了 校队 那样, 我对 自己 非常 失望, 眼泪 都 出来了。”
code:
awk '
BEGIN{
while(getline < "jordan"){
ret=index($0,"乔丹");
if(ret>0) printf("the index of \"乔丹\"is %d\n",ret);
}
close("jordan");
}'
./index.sh
the index of "乔丹"is 8
the index of "乔丹"is 22
注意:index(str1,str2)如果能找到str2在str1中,那么返回相应的位置,位置是从1开始的。
截取特定区域的文本
awk 'BEGIN{
info="I love linux";
result=substr(info,8,5);
print result;
}'
说明: substr(info,8,5)中8是开始的位置,5是截取的长度。同时,info开始的位置标号1.
将文本中的数字全部删除
awk 'BEGIN {
contents="abcd123erf567ghijk";
gsub(/[0-9]/,"",contents);
print contents;
}'
get:
abcderfghijk
注意:
gsub(r,s)在输入文件中用s替换r
gsub(r,s,t)在t中用s替换r
sub(r,s,t)在t中第一次出现的r替换成s
我们将gsub()改成sub():
awk 'BEGIN {
contents="abcd123erf567ghijk";
sub(/[0-9]/,"",contents);
print contents;
}'
get
abcd23erf567ghijk