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 数组下标分隔符(默认值是\034)。
#以'----------'替换行为记录分隔符,以‘|’替代空格为输字段分隔符
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("%d\t%.1fG(%.0f%)\t%.1fG\t%.1fG\n",$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 "\t\tuid:" $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:%s\n",NR,$0)}\
4$1 !~ /[A-Za-z0-9]/{printf("line %d,non alpha and numeric user id:%d: %s\n,NR,$0)}\
5$2 == "*" {printf("line %d, no password: %s\n",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 "\047 Hello! \047"} -- 遇到匹配行以后打印 ' Hello! '.\047 代表单引号。
{print $1,$2} -- 因为没有模式控制,打印每一行的前两个域。
6 、 awk '$1 ~ /101/ {print $1}' file
显示文件中第一个域匹配 101 的行(记录)。
7 、 awk 'BEGIN { OFS="%"} {print $1,$2}' file
通过设置输出分隔符( OFS="%" )修改输出格式。
8 、 awk 'BEGIN { max=100 ;print "max=" max} BEGIN
表示在处理任意行之前进行的操作。
{max=($1 >max ?$1:max); print $1,"Now max is "max}' file
取得文件第一个域的最大值。
(表达式 1? 表达式 2: 表达式 3 相当于:
if ( 表达式 1)
表达式 2
else
表达式 3
awk '{print ($1>4 ? "high "$1: "low "$1)}' file
9 、 awk '$1 * $2 >100 {print $1}' file
显示文件中第一个域匹配 101 的行(记录)。
10 、 awk '{$1 == 'Chi' {$3 = 'China'; print}' file
找到匹配行后先将第 3 个域替换后再显示该行(记录)。
awk '{$7 %= 3; print $7}' file
将第 7 域被 3 除,并将余数赋给第 7 域再打印。
11 、 awk '/tom/ {wage=$2+$3; printf wage}' file
找到匹配行后为变量 wage 赋值并打印该变量。
12 、 awk '/tom/ {count++;}
END {print "tom was found "count" times"}' file END
表示在所有输入行处理完后进行处理。
13 、 awk 'gsub(/\$/,"");gsub(/,/,""); cost+=$4;
END {print "The total is $" cost> "filename"}' file
gsub 函数用空串替换 $ 和 , 再将结果输出到 filename 中。
1 2 3 $1,200.00
1 2 3 $2,300.00
1 2 3 $4,000.00
awk '{gsub(/\$/,"");gsub(/,/,"");
if ($4>1000&&$4<2000)
c1+=$4;
else if ($4>2000&&$4<3000)
c2+=$4;
else if ($4>3000&&$4<4000)
c3+=$4;
else c4+=$4; }
END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file
通过 if 和 else if 完成条件语句
awk '{gsub(/\$/,"");gsub(/,/,"");
if ($4>3000&&$4<4000) exit;
else c4+=$4; }
END {printf "c1=[%d];c2=[%d];c3=[%d];c4=[%d]\n",c1,c2,c3,c4}"' file
通过 exit 在某条件时退出,但是仍执行 END 操作。
awk '{gsub(/\$/,"");gsub(/,/,"");
if ($4>3000) next;
else c4+=$4; }
END {printf "c4=[%d]\n",c4}"' file
通过 next 在某条件时跳过该行,对下一行执行操作。
14 、 awk '{ print FILENAME,$0 }' file1 file2 file3>fileall
把 file1 、 file2 、 file3 的文件内容全部写到 fileall 中,格式为打印文件并前置文件名。
15 、 awk ' $1!=previous { close(previous); previous=$1 }
{print substr($0,index($0," ") +1)>$1}' fileall
把合并后的文件重新分拆为 3 个文件。并与原文件一致。
16 、 awk 'BEGIN {"date"|getline d; print d}'
通过管道把 date 的执行结果送给 getline ,并赋给变量 d ,然后打印。
17 、 awk 'BEGIN {system("echo \"Input your name:\\c\""); getline d;print "\nYour name is",d,"\b!\n"}'
通过 getline 命令交互输入 name ,并显示出来。
awk 'BEGIN {FS=":";while(getline< "/etc/passwd" >0) { if($1~"050[0-9]_") print $1}}'
打印 /etc/passwd 文件中用户名包含 050x_ 的用户名。
18 、 awk '{ i=1;while(i
awk '{ for(i=1;i
type file|awk -F "/" '
{ for(i=1;i
{ if(i==NF-1) { printf "%s",$i }
else { printf "%s/",$i } })'
显示一个文件的全路径。
用 for 和 if 显示日期
awk 'BEGIN {
for(j=1;j<=12;j++)
{ flag=0;
printf "\n%d 月份 \n",j;
for(i=1;i<=31;i++)
{
if (j==2&&i>28) flag=1;
if ((j==4||j==6||j==9||j==11)&&i>30) flag=1;
if (flag==0) {printf "%02d%02d ",j,i}
}
}
}'
19 、在 awk 中调用系统变量必须用单引号,如果是双引号,则表示字符串
Flag=abcd
awk '{print '$Flag'}' 结果为 abcd
awk '{print "$Flag"}' 结果为 $Flag
---------------------------------awk应用小结(所有命令行均经调试)
1.调用awk:
第一种方式:命令行方式
awk [-F field-separator] 'commands' input-file(s)
[-F域分隔符]是可选的,因为awk使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,如果要浏览诸如passwd文件,此文件各域以冒号作为分隔符,则必须指明-F选项,如:
awk -F: 'commands' input-file
第二种方式是将所有awk命令插入一个文件,并使awk程序可执行,然后用awk命令解释器作为脚本的首行,以便通过键入脚本名称来调用它。
第三种方式是将所有的awk命令插入一个单独文件,然后调用:
awk -f awk-scrīpt-file input-files(s)
-f选项指明在文件awk_scrīpt_file中的awk脚本,input_file(s)是使用awk进行浏览的文件名。
模式和动作
任何awk语句都由模式和动作组成。在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。如果省略模式 部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊字段 BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。END语 句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。
域和记录
使用$1,$3表示参照第1和第3域,注意这里用逗号做域分隔。如果希望打印一个有5个域的记录的所有域,可使用$0,意即所有域。
为打印一个域或所有域,使用print命令。这是一个awk动作
模式和动作
模式 :两个特殊断 BEGIN和END
动作 :实际动作大多在{}内指明
输出
1.抽取域
awk -F: '{print $1}' /etc/passwd
2.保存输出
awk -F: '{print $1}' /etc/passwd | tee user 使用tee命令,在输出文件的同时,输出到屏幕
使用标准输出
awk -F: '{print $1}' /etc/passwd >user3
4.打印所有记录
awk -F: '{print $0}' /etc/passwd
5.打印单独记录
awk -F: '{print $1,$4}' /etc/passwd
6.打印报告头
awk -F: 'BEGIN {print "NAME\n"} {print $1}' /etc/passwd
7.打印结尾
awk -F: '{print $1} END {print "this is all users"}' /etc/passwd
条件操作符
1.匹配
awk -F: '{if($1~/root/) print }' /etc/passwd //{if($1~/root/) print}表示如果field1包含root,打印它
2.精确匹配
使用等号 ==
awk -F: '{if($3=="0") print }' /etc/passwd
3.不匹配
!~
awk -F: '{if($1!~/linuxtone/) print }' /etc/passwd
!=
精确不匹配
awk -F: '{if($1!="linuxtone") print }' /etc/passwd
4.小于
<
5.小于等于
<=
6.大于
>
.........
7.设置大小写
awk '/[Rr]oot/' /etc/passwd
8.任意字符
awk -F: '{if($1~/^...t/) print}' /etc/passwd //^...t表示第四个字幕是t
9.或关系匹配
awk -F: '{if ($1~/(squid|nagios)/) print}' /etc/passwd
10.行首
awk '/^root/' /etc/passwd // ^root(行首包含root)
11.AND &&
awk -F: '{if($1=="root" && $3=="0") print}' /etc/passwd
12.OR ||
打印有多少行记录
awk 'END {print NR}' /etc/passwd
设置输入域到变量名
awk -F: '{name=$1; path=$7; if(name~/root/) print name "\tpath is:" path}' /etc/passwd
域值比较操作
awk '{if($6<$7) print $0}' input-file
修改文本域只显示修改改记录
awk -F: '{if($1=="nagios") {$1="nagios server" ; print }}' /etc/passwd
文件长度相加
ls -l|awk '/^[^d]/ {print $9"\t" $5} {tot+=$5} END {print "total kb:"tot}'
内置的字符窜函数
gsub(r,s) 在整个$0中用s替代r
gsub(r,s,t) 在整个t中用s替代r
index(s,t) 返回s中字符串t的第一位置
length(s) 返回s长度
match(s,r) 测试s中是否包含匹配r的字符串
split(s,a,fs) 在fs上将s分成序列a
sub(s, ) 用$0中最左边也是最长的字符串替代
subtr(s,p) 返回字符串s中从p开始的后缀部分
substr(s,p,n) 返回字符串s中从p开始长度为n的后缀部分
1.gsub
awk 'gsub(/^root/,"netseek") {print}' /etc/passwd 将与root开头的root替换为netseek
awk 'gsub(/0/,2) {print}' /etc/fstab
awk '{print gsub(/0/,2) $0}' /etc/fstab
2.index
awk 'BEGIN {print index("root","o")}' 查询字符串root中o出现的第一位置
awk -F: '$1=="root" {print index($1,"o")" "$1}' /etc/passwd
awk -F: '{print index($1,"o") $1}' /etc/passwd
3.length
awk -F: '{print length($1)'} /etc/passwd
awk -F: '$1=="root" {print length($1)}' /etc/passwd
4.match (在ANCD中查找C的位置)
awk 'BEGIN {print match("ANCD",/C/)}'
5.split
返回字符串数组元素个数
awk 'BEGIN {print split("123#456#789", myarray, "#")}'
6.sub 只能替换指定域的第一个0
awk 'sub(/0/,2) {print }' /etc/fstab
7.substr
按照起始位置及长度返回字符串的一部分
awk 'BEGIN {print substr("www.linuxtone.org",5,9)}' //第5个字符开始,取9个字符。
awk 'BEGIN {print substr("www.linuxtone.org",5)}' //第5个位置开始,取后面的所有.
字符串屏蔽序列
\b 退格键
\f 走纸换页
\n 新行
\r 回车
\t tab
\c 任意其他特殊字符
\ddd 八进制
很简单的例子
awk -F: '{print $1,"\b"$2,"\t"$3}' /etc/passwd 输出函数printf(注意是printf不是print,两者效果不同的)
printf函数拥有几种不同的格式化输出功能
printf修饰符
- 左对齐
Width 域的步长0表示0步长
.prec 最大字符串长度,或小数点右边的位数
awk printf格式
%c ASCII字符
%d 整数
%e 浮点数,科学计数法
%f 浮点数
%g awk决定使用哪种浮点数转换,e或者f
%o 八进制数
%s 字符串
%x 十六进制数
1.字符串转换
echo "65" | awk '{printf"%c\n",$0}'
awk 'BEGIN {printf "%c\n",65}'
awk 'BEGIN {printf "%f\n",999}'
2.格式化输出
awk -F: '{printf "%-15s %s\n",$1,$3}' /etc/passwd
awk -F: 'BEGIN {printf"USER\t\tUID\n"} {printf "%-15s %s\n",$1,$3}' /etc/passwd
3.向一行awk命令传值
who | awk '{if ($1 == user) print $1 " you are connected to:" $2}' user=$LOGNAME
4.awk脚本文件 (在文件名字后面加后缀.awk方便区分)
#!/bin/awk -f
BEGIN{
FS=":"
print "User\t\tUID"
print"____________________________"
}
{printf "%-15s %s\n",$1,$3}
END{
print "END"
}