AWK学习笔记

34 篇文章 0 订阅
2 篇文章 0 订阅
AWK学习笔记


如下的内容来自《sed&awk》和自己的一些体会,如有不妥的地方,烦请指正,多谢~


1.AWK是基于输入语句的,文件中有多少句子,AWK就会被调用多少次。
这个循环是AWK提供的,不用我们去实现。


2.awk的基本结构包括三部分
由于awk主要是处理输入的文件内容的,所以:
  2.1执行前-->输入前执行的操作,有"BEGIN"标示,
  2.2执行中-->awk开始读取输入文件中的内容,并按行执行处理,
  2.3当awk读完输入文件,即awk处理完了所有的行之后要进行的处理,
     这部分使用"END"标示。


3.执行AWK,我认为有两种方式:
  1>直接在命令行输入完整的命令
   基本语法结构:
awk 'BEGIN {  }  /^$/{  } END{   }' input_file
        ---  -----| --- |----|---|--- ----  ----------
         A     B     C    D    E   F   G       H
    A.这是awk命令标示,awk命令+'执行的命令'+input_file,执行的命令必须用
      单引号包裹,这是awk最最基本的命令格式
    B.输入执行前的操作(我们先叫准备操作)的标示符,
    C.准备操作的具体执行命令,这部分命令需要放到花括号中,
      如果准备操作包括很多动作,我们可以使用嵌套多个花括号以使命令更清晰。
    E.先说E,因为这个是输入执行的具体命令,同样花括号可以嵌套使用
    D.模式匹配(下文有详细介绍),这是执行E的条件,也就是说必须满足D,才执行E,
      但是D和E的操作对象都是
      input_file中的每一行。上面例子的/^$/意思是空行,就是发现input_file中
      的空行就执行E。
    F.完成后操作标示符
    G.完成后具体指令,同样花括号也可以嵌套
    H.输入文件。    
    注:BC可以没有,FG也可以没有




   2>把具体的命令写入到脚本,然后用awk命令调用脚本awksrc,具体格式如下:
     awk -f awksrc input_file
     awksrc是awk脚本文件,其实我认为就是上面介绍的''之间的部分。
     input_file是要处理的输入文件




4.注释使用#


5.模式匹配,输入行和我们设置的模式匹配了,采取执行上文E部分的命令
  例子:
  /^$/{E} #如果是空行就执行E
  /[0-9]+/{E} #匹配数字,元字符+是正则表达式元字符扩展集中的一部分,表示一个或更多
  /[A-Za-z]+/{E}
  
6.记录和字段
6.1字段和引用的分离
awk允许使用字段操作符$来指定字段。
若文件test中只有一行,内容为:hmy xian 28 ,13309249541
$0表示整行内容
$1表示hmy
$2表示xian
$3表示28
$4表示,13309249451
awk默认的字段分隔符是空格" ",所以上述行就被默认分成了四个域
awk '{print $0,$1$2,$3,$4}' test
那么打印的结果: hmy xian 28 ,13309249541 hmy xian 28 ,13309249541
                 ------------------------|---|----|--|-------------
                            $0            $1   $2  $3     $4


我们可以使用-F选项来修改域分隔符,
awk -F"," '{print $0"--"$1"--"$2}' test
打印的结果就是:hmy xian 28 ,13309249541-- hmy xian 28 --13309249541
                ------------------------  -------------  -----------
                     $0整个字串               $1            $2
上述这个操作也可以通过如下命令实现:
awk 'BEGIN {FS = ","} {print $0"--"$1"--"$2}' test
FS是系统变量,将下文介绍。在处理真正的输入行之前的准备操作阶段修改FS
来改变字段分隔符。


6.2使用"~"匹配域
若test文件包含如下几行:
drwxr-xr-x 12 hmy hmy    4096 2012-10-31 02:48 hmy
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Desktop
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Documents
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Music
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Pictures
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Public
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Templates
drwxr-xr-x  2 hmy hmy    4096 2011-12-27 21:33 Videos
drwxr-xr-x  4 hmy hmy    4096 2012-10-31 00:01 Downloads


我们想检索这个文件,打印包含Music的行,则可以:
awk '$8 ~ /Music/{print $0}' test


解释一个比较复杂的例子:
awk '$1 ~ /1?(-| )?\(?[0-9]+\)?( |-)?[0-9]+-[0-9]+/{print $0}' input_file
     ----------------------------------------------


暂且不考虑input_file的内容,先分析下模式匹配的意思
"1?"表示出现0个或一个1;
"(-| )?"表示在随后的位置上查找一个连字符或者一个空格,或者什么都没有
"\(?"表示查找0个或一个左括号,反斜杠能防止将"("解释成用于分组的元字符
"[0-9]+"表示查找一到多位数字


7.表达式


转义序列:
\a 报警字符,通常是ASCII BEL字符
\b 退格键
\f 走纸符
\n 换行符
\r 回车
\t 水平制表符
\v 垂直制表符
\ddd 将字符表示为1到3位八进制
\xbex 将字符表示为16进制
\c 任何需要字面表示的字符c


awk变量
awk变量是大小写敏感的, awk能自动初始化变量为0或者为空
x=1
z="hello"
z="Hello" "World"




算术操作符:
+
-
*
/
%
^ 取幂
** 取N次方


赋值操作符:
++
--
+=
-=
*=
/+
%=
^=
**=


例子:
统计当前目录所有文件的大小:
ll | awk '{sum += $5} END{print sum}'










8.系统变量
awk中有两种系统变量
1>第一种:定义的变量默认值可以被改变,如分隔符FS的默认值是空格
2>第二种:变量的值可以用于报告或数据处理中,当前记录中字段的个数NF


例如:
FS字段分隔符,默认为空格(" ")--field spliter;

RS记录分隔符,默认为换行符--recorder spliter;

NR记录索引--number of recoder

OFS输出字段分隔符


NF当前输入记录中字段的个数--number of field
FNR 用来表示与当前输入文件相关的当前记录的代码
FILENAME记录当前输入文件的名字;
NR是当前记录在输入文件的位置,如果以换行符区分记录的话,NR就是行号
如:awk '$1 ~ /1?(-| )?\(?[0-9]+\)?( |-)?[0-9]+/{print NR". " $0}' input_file
这样使用NR的话,就是打印出满足模式匹配规则的行的同时,在行前加上该行
在原输入文件中的行号,并以". "区分






9.关系操作符和布尔操作


关系操作符:
< 小于
> 大于
<= 小于等于
>= 大于等于
== 相等的
!=      不相等
~     匹配
!- 不匹配


布尔操作符:
|| 逻辑或
&& 逻辑与
! 逻辑非


10.格式化打印
awk支持格式化打印,之前用到的print,在结果后自动添加换行符并输出
我们可以使用printf替换print。
printf的语法格式:
printf(Format-expression [, arguments])
其中圆括号是可选的,可以写成printf 格式表达式 参数列表


printf的格式说明符:
c
d
i 十进制整数
e 浮点格式
E 浮点格式
f 浮点格式
g e或f的转换形式,长度最短,末尾的0被去掉
G E或f的转换形式,长度最短,末尾的0被去掉
O 无符号的八进制
s
u 无符号十进制
x 无符号十六进制,用a-f表示
X 无符号十六进制,用A-F表示


11.从命令行向awk脚本传递参数
awk -f awksrc var=100 test
要传递的参数必须放在awk脚本文件和输入文件之间,参数var初始化时,
等号两边不能有空格


awksrc:
BEGIN{}
{}
END{print $0", " var}


test:
1111111
2222222


执行结果:
1111111, 100
2222222, 100


awk的条件,循环语句和C语言的非常类似
12.条件语句
13.循环语句
14.数组
15.多维数组
16.函数
1>内置算术函数
2>整数函数
int()#移除小数点
3>生成随机数
rand()#生成0~1之间的浮点型随机数
4>字符串函数
gsub(r,s,t)#在字符串t中用字符串s替换和正则表达式r匹配的所有字串。
           #返回替换的个数,如果没有给出t,默认为¥0


index(s,t) #返回子字串t在字符串s中的位置,如果没有指定s,则返回0


length(s)  #返回字串s的长度,当没有给出s时,返回$0的长度


match(s,r) #如果正则表达式r在s中出现,则返回出现的起点位置,如果s
           #中没有发现r,则返回0,设置RSTART和RLENGTH的值


split(s,a,sep) #使用字段分隔符sep将字符串分解到数组a的元素中,返回
               #元素的个数,如果没有给出sep,则使用FS,数组分割和
               #字段分割采用同样的方式


sprintf("fmt", expr) #expr 使用printf格式说明


sub(r,s,t) #在字符串t中s替换正则表达式r的首次匹配。如果成功则返回1
           #如果没有给出t,默认为$0。


subsre(s,p,n) #返回字符串s中从位置p开始最大长度为n的子字符串。如果没有给出n,
              #返回从p开始剩余的字符串。


tolower(s)  #将字符串s中的所有的大写字符转换成小写,并返回新字串


toupper(s)  #将字符串中的小写字符转换成大写,并返回新字串。


17.自定义函数


function xxx_name (parmeter-list)
{
...
statements
...


}








18.在awk中获得shell命令执行的结果,使用getline函数
如"whoami" | getline#这样就能得到whoami的结果,
若想把这个结果赋给一个变量,可以这样
"whoami" | getline result
如:BEGIN {"who am i" | getline res} {print res}




19.关闭管道 close()
理由:
1>每次只能打开一定数量的管道
2>关闭管道,可以使命令运行多次,如date
3>为了得到一个输出管道来完成它的工作


20.在awk中执行shell命令使用函数system()
如果我们要把001路径下的所有.c文件拷贝到002路径下,可能方法有很多,现在看看我的实现方式
find ./001/ -name "*.c" | awk '{system("cp " $0 "./002/")}{print $0} END{print "copy end!"}'
在这里一定要注意system("cp " $0 " ./002/"),在cp后面有个空格,在./002/前面也有个空格,要是没有
这两个空格,system就会把它的参数解析成cp$0./002/, 当然$0会被替换,但是是一个没有空格的字串,
就不是"cp X Y"的格式了。




====================================================================

                      搜集的一些好玩的脚本

====================================================================

1.统计文本中空行数:

awk '/^$/{sum++} END{print sum}'  input_file

2.统计全为数字的行:

awk '/^[0-9]+$/{sum++} END{print sum}' X

3.统计全为引文字母的行数:

awk '/^[A-Za-z]+$/{sum +=1; print $0} END{print sum}' X

4.统计包含test的行:

awk '/test/{sum++; print $0} END{print sum}' X

5.打印文本时,在行首加上行号:

awk "print NR ". " $0" X

6.按字符取内容

对于只包含ASC码的文本,如果要按字符提取的话,我们可以把FS设置为空

如test文件中包含如下内容:

asdfg

awk 'BEGIN {FS=""} {print $1", "$2", "$3", "$4", "$5}' test

打印的结果就是a, s, d, f, g











 







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值