概述
ttp://bbs.linuxtone.org/thread-1714-1-1.html
Awk学习笔记 http://www.linux.gov.cn/shell/awk.htm
是一种用于处理数据和生成报告的编程语言
awk 倾向于将一行分成数个字段来处理;
------------------------linlin
awk '{print}' /etc/passwd :打印/etc/passwd所有内容
awk -F : '{print $1}' /etc/passwd :以 ":" 为分隔符 ,打印/etc/passwd第一字段,也就是用户名
awk -F : '{print $1 " " $2}' /etc/passwd :同上功能,打出第1,第二字段。 中间加个空格输出。
awk 'BEGIN{FS=":";OFS="t";ORS="n"}{print $1,$2}' /etc/passwd
*** FS:字段分隔符
OFS:输出字段分隔符
ORS:输出记录分隔符
以上命令为以 : 为分隔符,每个字段用t隔开,输出一行后n (换行), 输出第1,2字段。中间用,隔开
awk '{print NR}' /etc/passwd :读取/etc/passwd的每一行行号 (NR至今的读取记录数)
awk 'END{print NR}' /etc/passwd : 加了个END,读最后一个读取记录数的数字! 输出结果:29 表示29个用户
awk '/root/' /etc/passwd :输出 /etc/passwd里包含 root 这个字眼的 记录!打印出来 。'/ /'里表示的是符合字符
awk '{if($1~/root/) print $0}' /etc/passwd : 如果第一个字段里有符合root字眼的,打印当前行,$0表示当前行(当前记录)
awk '/^[Rr]oot/' /etc/passwd : '//'里表示匹配字符 ^表示匹配第一个字母 [Rr]表示这个字母是R或者r也可以
所以上面的语句表示:第一个字母符合Root或者root就打印改记录条
awk '$2~/^..u/' /etc/passwd : ~/表示匹配,这里表示第2个字段第3个字母为u的话,就打印出该行
awk '/(lin|root)/' /etc/passwd :记录里有匹配 lin或者root的!就打印出来
echo ababab | awk 'gsub(/a/,"c")' : 输出 ababab 再把输出结果交给awk处理,最后吧 a换成了c .输出为 cbcbcb
awk '{if($4!~"301|302") print $0}' filename :要是 第4个字段, 不匹配 301或者 302!就打印出该记录 !~表示不匹配,~表示匹配
awk '$1!~/^.-/' 不匹配第2个字符是 -
cat XXX.txt |grep -v "^#"|grep -v "^$" > XXX.txt 把开头是#的!全部删掉
cat t.log |awk '{if($3!~/note/) print $0}'|grep "2010-11-14"|wc -l 不匹配note
cat t.log |awk '{if($3~/note/) print $0}'|grep "2010-11-14"|wc -l 匹配note
cat t.log |grep -E "2010-11-14|2010-11-15" |more
cat t.log |grep -E "2010-11-14|2010-11-15" |awk '{if($3~/test/) print $0}' |more
cat /etc/passwd |cut -d ":" -f1 |grep root
cat tmp |awk '{if($3~/paijiang/ && $1~/2010-11-14/) print $0}'|wc -l
ps aux| awk '{print $2}'
cat /proc/meminfo | awk '/MemTotal/{print $2}' 内存大小
df -h | awk '{print $5}' |grep -v 'User%' grep -v 是删除包含 User% 的行
常用的作用格式:
awk ‘样式’ 文件
awk ‘{操作}’ 文件
awk ‘ { 样式 操作}’ 文件
awk是一种用于处理数据和生成报告的编程语言。
一般的使用格式是:
awk '{pattern + action}' filenames}
pattern指在每一行中进行匹配的条件,action指针对符合条件的行进行的操作,filenames是输入的文件名。
假设data文件中有以下数据:
1 donald 305 20050129
2 chin 102 20040129
3 mark 304 20040229
下面对这个文件进行操作:
awk '{print $1, $2, $3, $4}' data
而$1,$2...则相应代表分割后的列
逗号则让列与列之间插入空格
$0表示整行
输出:
1 donald 305 20050129
2 chin 102 20040129
3 mark 304 20040229
-----------------awk 转义字符
b 退格键
t tab键
f 走纸换页
ddd 八进制值
n 新行
c 任意其他特殊字符,例如\为反斜线符号
r 回车符
------------条件操作符
1 匹配 ~
awk ‘{if($1~/root/) print $0}’ /etc/passwd #如果field1包含"root",打印该行
2.精确匹配
!= ==
3.不匹配
!~
4.大小比较
> >= < <=
5.设置大小写
awk ‘/^[Rr]oot/’ /etc/passwd # 打印包含行首为Root或者root的行
6.任意字符 .
awk ‘$2~/^…a/’ /etc/passwd # 打印第二个字段开头第四个字母为t的行
7.或关系匹配 |
awk ‘/(root|ftp)/’ /etc/passwd #打印包含"root"或者"ftp"的行
8.AND && OR ||
awk ‘{$1~/mail/ && $7==/bin/bash}’ /etc/passwd
内置字符串函数
gsub(r,s,t) 在字符串t中,用字符串s替换和正则表达式r匹配的所有字符串。返回替换的个数。如果没有给出t,缺省为$0
index(s,t) 返回s 中字符串t 的位置,不出现时为0
length(s) 返回字符串s 的长度,当没有给出s时,返回$0的长度
match(s,r) 返回r 在s 中出现的位置,不出现时为0。设置RSTART和RLENGTH的值
split(s,a,r) 利用r 把s 分裂成数组a,返回元素的个数。如果没有给出r,则使用FS。数组分割和字段分割采用同样的方式
sprintf(fmt,expr_list) 根据格式串fmt,返回经过格式编排的expr_list
sub(r,s,t) 在字符串t中用s替换正则表达式t的首次匹配。如果成功则返回1,否则返回0。如果没有给出t,默认为$0
substr(s,p,n) 返回字符串s中从位置p开始最大长度为n的字串。如果没有给出n,返回从p开始剩余的字符串
tolower(s) 将串s 中的大写字母改为小写,返回新串
toupper(s) 将串s 中的小写字母改为大写,返回新串
-----------------------awk的环境变量
变量 描述
$n 当前记录的第n个字段,字段间由FS分隔 。
$0 完整的输入记录。
ARGC 命令行参数的数目。
ARGIND 命令行中当前文件的位置(从0开始算)。
ARGV 包含命令行参数的数组。
CONVFMT 数字转换格式(默认值为%.6g)
ENVIRON 环境变量关联数组。
ERRNO 最后一个系统错误的描述。
FIELDWIDTHS 字段宽度列表(用空格键分隔)。
FILENAME 当前文件名。
FNR 同NR,但相对于当前文件。
FS 字段分隔符(默认是任何空格)。
IGNORECASE 如果为真,则进行忽略大小写的匹配。
NF 当前记录中的字段数。 ------------------------- 域的总数
NR 当前记录数。
OFMT 数字的输出格式(默认值是%.6g)。
RS 记录分隔符(默认是一个换行符)。 -------------awk是以行为单位,也可以在这里替换为你需要的分割单位
OFS 输出字段分隔符(默认值是一个空格)。 --------awk默认以空格为字段分割符
ORS 输出记录分隔符(默认值是一个换行符)。
RLENGTH 由match函数所匹配的字符串的长度。
RSTART 由match函数所匹配的字符串的第一个位置。
SUBSEP 数组下标分隔符(默认值是 34)。
#以'----------'替换行为记录分隔符,以‘|’替代空格为输字段分隔符
awk -v RS='----------' -v OFS='|' '$1=$1' $log > 1.txt
----------------------------------gawk专用正则表达式元字符
一般通用的元字符集就不讲了,可参考我的Sed和Grep学习笔记。以下几个是gawk专用的,不适合unix版本的awk。
Y
匹配一个单词开头或者末尾的空字符串。
B
匹配单词内的空字符串。
<
匹配一个单词的开头的空字符串,锚定开始。
>
匹配一个单词的末尾的空字符串,锚定末尾。
w
匹配一个字母数字组成的单词。
W
匹配一个非字母数字组成的单词。
‘
匹配字符串开头的一个空字符串。
'
匹配字符串末尾的一个空字符串。
-------------------------------------------- 检索用户ID值为502的用户名。
下面的命令不好:
$ grep 502 /etc/passwd | cut -d: -f1
这条命令也不够好:
$ grep 502 /etc/passwd | awk -F":" '{print $1}'
这才是一条好的命令:
$ awk -F":" '$3==502{print $1}' /etc/passwd
正如以上示例,用一条简单的awk命令就可以完成检索任务。
--------------------------------------------
TEXT1=`cat "f1"`
RESULT1=`echo "$TEXT1" | awk 'BEGIN {FS=","}{print $1}'` awk取列并赋值
awk '/donald/ {print $4}' data 匹配当data文件中包含字符串"donald"的行,输出第4列的值:
awk '/donald|chin/ {print $1, $2}' data 这里的"|"应该是或的作用,而不是管道,输出:
1 donald
2 chin
awk '/a[rl]/ {print $1, $2}' data 兼容perl的正则表达式,匹配包含"ar"或"al"的列 ,输出:
1 donald
3 mark
awk '/a[rl]/ {print $1, $2, $3+1}' data 给第三列加上1再输出:
1 donald 306
3 mark 305
awk '/a[rl]/ {print $1, $2} {print $3+1}' data 匹配只对第一对花括号产生作用 ,输出:
1 donald
306
103
3 mark
305
awk 'FS="n" {print $1}' data 使用"n"而不是空格做为分隔符,输出:
1
2 chi
3 mark 304 20040229
awk 'FS="n" {OFS="-"} {print $1, $2}' data
把分隔符输出:
1-donald
2 chi- 102 20040129
3 mark 304 20040229-
awk 'FS="n" {OFS="-"} {print NR, $1, $2}' data
使用NR变量,num of row,即行号,输出:
1-1-donald
2-2 chi- 102 20040129
3-3 mark 304 20040229-
awk '{x=x+$3} {print NR, $3, x}' data
使用变量进行累加计算,输出:
1 305 305
2 102 407
3 304 711
awk '{x=x+$3} END {print NR, $3, x}' data
使用BEGIN和END在处理之前或之后显示结果,输出:
3 304 711
awk '{x=x+$3} {print NR, $3, x | "sort -nr"}' data
在awk内使用管道进行排序,输出:
3 304 711
2 102 407
1 305 305
cat command
{x=x+$3}
{print NR, $3, x | "sort -nr"}
awk -f command data
将指定写在文件中,输出:
3 304 711
2 102 407
1 305 305
$awk '$2 == "chin" { print $3 }' 1.txt
如果简单的输出不能处理您的程序中所需要的复杂信息,则可以尝试由 printf 命令获得的更加复杂的输出,其语法是
printf( format, value, value ...)
该语法类似于 C 语言中的 printf 命令,而格式的规格是相同的。通过插入一项定义如何打印数值的规格,可以定义该格式。格式规格包含一个跟有字母的 %。类似于打印命令,printf 不必包含在圆括号中,但是可以认为使用圆括号是一种良好的习惯。
下表列出 printf 命令提供的各种规格。
规格 说明
%c 打印单个 ASCII 字符
%d 打印十进制数
%e 打印数字的科学计数表示
%f 打印浮点表示
%g 打印 %e 或 %f;两种方式都更简短
%o 打印无符号的八进制数
s 打印 ASCII 字符串
%x 打印无符号的十六进制数
%% 打印百分号;不执行转换
可以在 % 与字符之间提供某些附加的格式化参数。这些参数进一步改进数值的打印方式:
参数 说明
- 将字段中的表达式向左对齐
,width 根据需要将字段补齐到指定宽度(前导零使用零将字段补齐)
.prec 小数点右面数字的最大字符串宽度或最大数量
====================
文件disk.txt:
disk used noused sum
0 209715 2097152 2306867
1 209715 2097152 2306867
2 209715 2097152 2306867
3 209715 2097152 2306867
现在我想把这个文档处理成这样
硬盘 已使用 未使用 默认大小 //英文改成中文
0 0.2G 2G 2.2G //209715k换算成G 1M=1024k 1G=1024M 并且限制小数位为1,后面加上单位名G
1 0.2G 2G 2.2G
2 0.2G 2G 2.2G
3 0.2G 2G 2.2G
======》》
awk '{if (NR==1) {print "硬盘t已使用t未使用t默认大小"} else {u=$2/1024/1024; n=$3/1024/1024; s=$4/1024/1024; p=$2/$4*100; printf("%dt%.1fG(%.0f%)t%.1fGt%.1fGn",$1,u,p,n,s)}}' disk.txt
============================
$cat file
user1 par11 par12
user2 par21 par22
user1 par31 par32
awk '{if($1=="'user1'") print $1,$2,$3}' file
这样会把结果user1 par11 par12
user1 par31 par32 都输出来
我想当$1匹配到第一个user1的时候,就输出结果。
=====>>>>
awk '{if($1=="'user1'") {print $1,$2,$3;exit}}' file
$ awk '{ print $0 }' /etc/passwd
在 Awk 中,变量 $0 表示整个当前行,因此 print 和 print $0 的作用完全相同。
$awk -F":" '{ print $1 $3 }' /etc/passwd
halt7
operator11
root0
shutdown6
sync5
bin1
$awk -F":" '{ print "username: " $1 "ttuid:" $3 }' /etc/passwd
如果第一个域大于第三个域,$1就赋值给max,否则$3就赋值给max。
$ awk '{max = {$1 > $3} ? $1: $3: print max}' test
将显示test文件第一列中以root开头的行。
$ awk '$1 ~/^root/' test
如果第一和第二个域相加大于100,则打印这些行。
$ awk '$1 + $2 < 100' test。
awk '$1 > 5 && $2 < 10' test,如果第一个域大于5,并且第二个域小于10,则打印这些行。
$ awk '/root/,/mysql/' test将显示root第一次出现到mysql第一次出现之间的所有行。
============12. 一个验证passwd文件有效性的例子
1$ cat /etc/passwd | awk -F: '
2NF != 7{
3printf("line %d,does not have 7 fields:%sn",NR,$0)}
4$1 !~ /[A-Za-z0-9]/{printf("line %d,non alpha and numeric user id:%d: %sn,NR,$0)}
5$2 == "*" {printf("line %d, no password: %sn",NR,$0)}'
1
cat把结果输出给awk,awk把域之间的分隔符设为冒号。
2
如果域的数量(NF)不等于7,就执行下面的程序。
3
printf打印字符串"line ?? does not have 7 fields",并显示该条记录。
4
如果第一个域没有包含任何字母和数字,printf打印“no alpha and numeric user id" ,并显示记录数和记录。
5
如果第二个域是一个星号,就打印字符串“no passwd”,紧跟着显示记录数和记录本身。
$ awk '/^(no|so)/' test-----打印所有以模式no或so开头的行。
*
$ awk '/^[ns]/{print $1}' test-----如果记录以n或s开头,就打印这个记录。
*
$ awk '$1 ~/[0-9][0-9]$/(print $1}' test-----如果第一个域以两个数字结束就打印这个记录。
*
$ awk '$1 == 100 || $2 < 50' test-----如果第一个或等于100或者第二个域小于50,则打印该行。
*
$ awk '$1 != 10' test-----如果第一个域不等于10就打印该行。
*
$ awk '/test/{print $1 + 10}' test-----如果记录包含正则表达式test,则第一个域加10并打印出来。
*
$ awk '{print ($1 > 5 ? "ok "$1: "error"$1)}' test-----如果第一个域大于5则打印问号后面的表达式值,否则打印冒号后面的表达式值。
*
$ awk '/^root/,/^mysql/' test----打印以正则表达式root开头的记录到以正则表达式mysql开头的记录范围内的所有记录。如果找到一个新的正则表达式root开头的记 录,则继续打印直到下一个以正则表达式mysql开头的记录为止,或到文件末尾。
awk '$1 ~/test/{count = $2 + $3; print count}' test,上式的作用是,awk先扫描第一个域,一旦test匹配,就把第二个域的值加上第三个域的值,并把结果赋值给变量count,最后打印出来。
$ awk '{if ($1 <$2) print $2 "too high"}' test。如果第一个域小于第二个域则打印。
$ awk '{if ($1 < $2) {count++; print "ok"}}' test.如果第一个域小于第二个域,则count加一,并打印ok。
$ awk '{if ($1 > 100) print $1 "bad" ; else print "ok"}' test。如果$1大于100则打印$1 bad,否则打印ok。
$ awk '{if ($1 > 100){ count++; print $1} else {count--; print $2}' test。如果$1大于100,则count加一,并打印$1,否则count减一,并打印$1。
====================awk有三种循环:while循环;for循环;special for循环。
*
$ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。变量的初始值为1,若i小于可等于NF(记录中域的个数),则执行打印语句,且i增加1。直到i的值大于NF.
*
$ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。
*
breadkcontinue语句。break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端。如:
{for ( x=3; x<=NF; x++)
if ($x<0){print "Bottomed out!"; break}}
{for ( x=3; x<=NF; x++)
if ($x==0){print "Get next item"; continue}}
*
next语句从输入文件中读取一行,然后从头开始执行awk脚本。如:
{if ($1 ~/test/){next}
else {print}
}
*
exit语句用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。
--------------------
1 、 awk '/101/' file 显示文件 file 中包含 101 的匹配行。
IXDBA.NET技术社区
awk '/101/,/105/' file
awk '$1 == 5' file
awk '$1 == "CT"' file 注意必须带双引号
awk '$1 * $2 >100 ' file
awk '$2 >5 && $2<=15' file
2 、 awk '{print NR,NF,$1,$NF,}' file 显示文件 file 的当前记录号、域数和每一行的第一个和最后一个域。
awk '/101/ {print $1,$2 + 10}' file 显示文件 file 的匹配行的第一、二个域加 10 。
awk '/101/ {print $1$2}' file
awk '/101/ {print $1 $2}' file 显示文件 file 的匹配行的第一、二个域,但显示时域中间没有分隔符。
3 、 df | awk '$4>1000000 '
通过管道符获得输入,如:显示第 4 个域满足条件的行。
4 、 awk -F "|" '{print $1}' file
按照新的分隔符 “|” 进行操作。
awk 'BEGIN { FS="[: t|]" } {print $1,$2,$3}' file
通过设置输入分隔符( FS="[: t|]" )修改输入分隔符。
Sep="|"
awk -F $Sep '{print $1}' file 按照环境变量 Sep 的值做为分隔符。
awk -F '[ :t|]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表空格、 : 、 TAB 、 | 同时做为分隔符。
awk -F '[][]' '{print $1}' file 按照正则表达式的值做为分隔符,这里代表 [ 、 ]
5 、 awk -f awkfile file 通过文件 awkfile 的内容依次进行控制。
cat awkfile /101/{print "