- 论坛徽章:
- 0
|
AWK介绍
9.1 调用awk
三种方式:
1. 命令行方式:
awk [-F filed-separator] 'commands' input-files
-F 指定分隔符(默认是空格或tab)
commands awk的命令
input-files 要处理的文件
2. 将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它
3. 将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-script-file input-files
-f 指明调用脚本名
input-files 待处理的文件
9.2 awk脚本
在命令中调用awk时,awk脚本由各种操作和模式组成。
awk每次读一条记录或一行,并使用指定的分隔符分隔指定域。当新行出现时,awk命令获悉已读完整条记录,然后在下一个记录启动读命令,这个读进程将持续到文件尾或文件不再存在。
9.2.1 模式和动作
任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发条件。处理即对数据进行的操作。如果省略模式部分,动作将时刻保持执行状态。
模式可以是任何条件语句、复合语句或正则表达式,包括两个特殊字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句用在任何文本浏览动作之前,之后文本浏览动作依据输入文件开始执行。END语句用在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明模式,awk总是匹配。
实际动作在大括号{}内指明。动作大多数用来打印,但还有些更长的代码诸如if和循环语句及循环退出结构。如果不指明采取动作,awk将打印出所有浏览出来的记录。
9.2.2 域和记录
awk执行时,其浏览域标记为$1,$2…$n,这种方法称为域标识。当需要指定多域时使用逗号,用于分隔,如$1,$3指定第一域和第三域,如果希望指定所有域可使用$0。
使用print命令执行打印操作,这是一个awk命令,需要用{}括起来。
1. 抽取域
举例: 现有一个grade.txt文件,内容如下:
$ cat grade.txt
M.Tansley 05/99 48311 Green 8 40 44
J.Lulu 06/99 48317 Green 9 24 26
P.Bunny 02/99 48 Yellow 12 35 28
J.Troll 07/99 4842 Brown-3 12 26 26
L.Tansley 05/99 4712 Brwon-2 12 30 28
此文本文件有7个域,以空格作为域分隔符
2. 保存awk输出
两种方式保存awk的输出结果:
重定向到文件:(屏幕无显示)
$ awk '{print $0}' grade.txt >wow
使用管道将输出结果传给tee:(屏幕显示结果)
$ awk '{print $0}' grade.txt|tee woww
3. 使用标准输入
几种方法:
$ belts.awk grade.txt
$ belts.awk 结束输入
9.2.3 元字符
\ ^ $ . [ ] | ( ) * + ?
其中+和?只适用于awk而不适用于grep或sed:
+ 匹配一个或一个以上前面的单字符
? 匹配0个或一个前面的单字符
举例:
/XY+Z/ 匹配XYZ、XYYYYZ
/XY?Z/ 匹配XYZ、XZ
9.2.4 条件操作符
操作符 描述
大于
>= 大于等于
~ 匹配正则表达式
!~ 不匹配正则表达式
1. 匹配
使用~紧跟正则表达式可以匹配域,也可以用if,条件需要用()括起来
举例:
查询棕带学员的所有情况(打印出$4匹配Brown的行)
$ awk '{if ($4~/Brown/) print $0}' grade.txt
或
$ awk '$0 ~ /Brown/' grade.txt
2. 精确匹配
使用==并用双引号括起条件可以精确匹配条件
举例:
$ awk '{if ($3 == "48") print $0}' grade.txt
3. 不匹配
使用!~紧跟正则表达式不匹配域
举例:
查询不是棕带的所有学员情况(打印出$4不匹配Brown的行)
$ awk '{if ($4!~/Brown/) print $0}' grade.txt
或
$ awk '$0 !~ /Brown/' grade.txt
4. 比较
由于几个比较大小符的使用方法都一样,就随便举一个例子:
$ awk '{if ($6 0 && $4 ~ /Brown/) print $0}' grade.txt
NF的一个强大功能是将变量$PWD的返回值传入awk并显示其目录:
$ echo $PWD | awk -F/ '{print $NF}'
显示文件名:
$ echo "/usr/apache/conf/httpd.conf" | awk -F/ '{print $NF}'
9.2.6 awk操作符
awk操作符的基本表达式可以划分为数字型、字符串型、变量型域及数组元素
= += -= *= /= %= ^= 赋值操作符
? 条件表达操作符
|| && ! 并、与、非
~ !~ 匹配操作符(匹配与不匹配)
>= 关系操作符
+ - * / % ^ 算术操作符
++ -- 前缀和后缀
1. 设置输入域到域变量名
在awk中,设置有意义的域名是一种好习惯,在进行模式匹配或关系操作时更容易理解。一般的变量名设置方式为name=$n,这里name为调用的域变量名,n为实际域号。多个域名设置之间用分号;分隔(请注意下面;的使用)
$ awk '{name = $1;belts = $4; if (belts ~ /Yellow/) print name" is belt "belts}' grade.txt
2. 域值比较操作
有两种方式测试一数值域是否小于另一数值域:
1) 在BEGIN中给变量名赋值
2) 在关系操作符中使用实际数值
通常在BEGIN部分赋值是很有益的,可以在awk表达式进行改动时减少很多麻烦。使用关系操作时必须用圆括号括起来。举例:
查询所有比赛中得分在27点一下的学生:
$ awk '{if ($6
收集awk的一些技巧方案
awk [opion] 'awk_script' input_file1 [input_file2 ...] awk的常用选项option有:
① -F fs : 使用fs作为输入记录的字段分隔符,如果省略该选项,wak使用环境变量IFS的值。
② -f filename : 从文件filename中读取awk_script。
③ -v var=value : 为awk_script设置变量。
1、删除重复的行
#awk '!a[]++'
2、将数据文件中的每个词的第一个字母变成大写
[email=dingyi@backup:~$]dingyi@backup:~$[/email]
cat test
linux is long live!!!
i am a cuer
[email=dingyi@backup:~$]dingyi@backup:~$[/email]
awk ',1,1); sub(/^./,toupper(first),); print }' test
Linux is long live!!!
I am a cuer
awk 请教
下面是文件一,文件二
$cat file1
00001 20
00002 31
00003 04
00004 56
00005 94
00006 73
00007 25
00008 86
00009 19
00010 52
$cat file2
00001 20
00007 28
00002 32
00004 56
00010 52
怎样的shell才能使file1、file2两个文件的$2不同的话,取出全局$0?
注意:比较两个文件的$2的时候,一定要第一列相同的情况下才比较
请大虾执教
li2002 2003-9-11 08:57
awk 请教
不就是找出不同行吗?
cat file1 file2|sort |uniq -u
deathcult 2003-9-11 09:15
awk 请教
paste file1 file2|awk '{if(($1==$3)&&($2!=$4))print$0}'
bjgirl 2003-9-11 09:38
awk 请教- #!/bin/ksh
- sort -n file1>nf
- sort -n file2>mf
- paste nf mf|awk '$1=$3 {print}'|awk '$2!=$4 {print}'
- rm nf mf
- 结果:
- 00002 31 00002 32
- 00004 04 00004 56
- 00007 56 00007 28
- 00010 94 00010 52
复制代码
killua 2003-9-11 10:05
awk 请教
回一楼,最近在学awk啦,而且你那样得到的数值是
00002 31
00002 32
00003 04
00005 94
00006 73
00007 25
00007 28
00008 86
00009 19
00010 52
00010 52
而我要的是
00002 31 32
00007 25 28
二楼的没有数值哦,而且应该是paste file1 file2|awk '{if ($1 == $3 && $2 != $4) print $0}'[/quote]
awk 请教
三楼的答案是错的,我要是结果是
00002 31 32
00007 25 28
把$1相同,而$2不同的列出来
admirer 2003-9-12 00:45
awk 请教
这不是一个简单的paste能解决的问题,而是一个以关键字连接的问题!- sort file1 >f1;sort file2 >f2; join -j1 1 f1 f2|awk '$2 != $3'
- 00002 31 32
- 00007 25 28
复制代码
killua 2003-9-12 03:30
awk 请教
[quote]原帖由 "yoof"]join -j1 1 f1 f2 请版主解释[/quote 发表:
以第一个文件的第一个域为索引键,连接f1,f2两个文件
文件处理
1.有文件gz.txt(工资)
4367422926350133100 张三 1250.00
4367422926351220178 李四 1300.00
4367422926351220546 王二 0
苏五丙 1340.00
4367422926351220178 孙六月 1390.00
…… ……
要求:按账号19位、姓名8位、工资8位来排列,且如姓名不足8位在之后补足,工资不足8位则在工资之前补。同时要求去掉工资为0的名单,没有账号在前补19位空格,并输出工资总数加以核对,处理后应如下排列:
4367422926350133100张三 1250.00
4367422926351220178李四 1300.00
苏五丙 1340.00
4367422926351220178孙六月 1390.00
…… ……
awk程序:
#------------------------------------
#shgz1.sh
sblank=" "
awk '$nf!="0"' $1 > tmp.txt #删除工资为0的人数
awk ' #如果没有账号补上空格
else
>' tmp.txt > $2
awk '$nf~/[0-9]/
end' $2
在awk中调用系统变量必须用单引号,如果是双引号,则表示字符串
Flag=abcd
awk '{print '$Flag'}' 结果为abcd
awk '{print "$Flag"}' 结果为$Flag
如何删除匹配之间的内容但不包括匹配行
我有这样一个文件:
Query=4567879
sequence jkaskdjgkjasgasa;jghsafgkas
jfaklslgjdla;;gsdakl;gd
score E
PUT-ASD-WEETED-001
PUT-ASD-WEQER5-001789
>PUT-ASD-WEETED-001
SDAGDSDS
>PUT-ASD-WEQER5-001789
DSGTSDTEW
.....
......
......
是这样的,我想删除
从score E
到以第一个以>开头的中间所有的行,但不包括score E行和第一以>开头的行
用
sed '/score E/,/^>/d' urfile
肯定是不行的,把score E行和第一以>开头的行也删掉了?
该怎么写呢?
其中要处理的文件中含有多个score E和第一以>开头的之间的行,均删掉。
awk -v p=1 '/score/{p=0}/>/{p=1}p' urfile
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/15566/showart_1909659.html |
|