awk初步

认识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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值