0
点赞
收藏
分享

微信扫一扫

(11.1)Awk工作原理


文章目录

  • ​​1.awk简介​​
  • ​​2.awk工作原理​​
  • ​​3.awk的格式化输出​​
  • ​​4.awk模式和动作​​
  • ​​5.awk脚本编程​​

1.awk简介

  • 作用:统计,分割,sed是直接修改文件
  • awk是一种编程语言,用于在linux/unix下对文本和数据进程处理。
    数据可以来自标准输入,一个或者多个文件,或者其它命令的输出。
    他支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。
    他在命令行中使用,但是更多是作为脚本来使用。
  • awk处理文本和数据的方式是这样,他逐行扫描文件,从第1行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作 (这里与sed一样)
    如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕)上;
    如果没有指定模式,则所有被操作所指定的行都被处理;
    gawk是awk的GUN版本。
  • awk的语法形式

awk [options] 'commands' filenames

options:
-F:定义输入字段分隔符,默认的分隔符是空格或者制表符(tab)

commands:
BEGIN{} {} END{}
行处理前 行处理 行处理后

注意:
BEGIN() 通常用于定义一些变量,eg:输入时,修改字段分隔符FS=":",输出结果时,按照OFS="---"分割
[root@jiwang]# awk 'BEGIN{FS=':';OFS='---'}' {print $1,$2} passwd
root---x
bin---x

BEGIN{}发生在读文件之前,看下面的执行结果eg;
[root@jiwang]# awk 'BEGIN{print 2/5}'
0.4
[root@jiwang]# awk 'BEGIN{print 2/5} {print "ok"} END{print "----"}' /etc/hosts
0.5
ok
ok
ok
----

  • awk的命令格式

(1)pattern类似正则,awk 'pattern' filename
awk '/root/' passwd

(2)行处理:awk '{action}' filename
awk -F: '{print $1}' passwd

(3)awk 'pattern {action}' filename
awk 'BEGIN{FS=":"} /root/{print $1 $2}' /etc/passwd

(4)command|awk 'pattern {action}'
df -P|grep '/'|awk '$4>23000 {print $4}'
-P:表示posix,逻辑卷不会换行

2.awk工作原理

  • awk -F: ‘{print $1,$3}’ /etc/passwd
    -F:等价于FS=":"
    ,会映射成OFS=","
    $0可以用暂存空间来理解
    (1)awk使用1行作为输入,并将这1行赋值给内部变量$0,每一行也可称之为一个记录,以换行符结束
    (2)然后,行被:(默认为空格或者制表符)分解成字段(或者域) , 每个字段存储在已编号的变量中,从$1开始, 最多达到100个字段
    (3)awk如何知道用空格来分隔字段的呢?因为有1个内部变量FS来确定字段分隔符。初始时,FS赋为空格
    (4)awk打印字段时,将以设置的方法使用print函数打印,awk在打印的字段间加上空格,因为$1,$3之间
    有一个逗号。
    逗号比较特殊,他映射为另一个内部变量,称之为输出字段分隔符OPS ,OPS默认为空格
    (5)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖掉原来的那个,然后将新的字符串分隔成字段并进行处理。该过程持续到所有行处理完毕。
  • 记录与字段相关的内部变量:man awk

$0:awk变量$0保存当前记录的内容
eg:awk -F : '{print $9}' /etc/passwd

NR:the total number of input records seen so far
eg:awk -F : '{print NR, $0}' /etc/passwd /wtc/hosts

FNR:the input record number in the current input file
eg:awk -F : '{print FNR, $0}' /etc/passwd /wtc/hosts

NF:保存记录的字段数,$1,$2,。。。$100,$NF指的是最后一个字段的内容
eg:awk -F: '{print $0,NF,$NF}' /etc/passwd

FS:输入字段分隔符,默认空格
eg:
awk -F: '/alice/{print $1,$3}' /etc/passwd
awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd 按照空格,tab,:分隔
awk 'BEGIN{FS=":"} {print $1}' /etc/passwd


OFS:输出字段分隔符
eg:
awk -F: '/alice/{print $1,$2}' /etc/passwd
awk 'BEGIN{FS=":"{print $1,$3}}' /etc/passwd
awk 'BEGIN{FS=":";OFS="+++"} /^root/{print $1,$2}' /etc/passwd

(11.1)Awk工作原理_正则表达式


(11.1)Awk工作原理_正则表达式_02


(11.1)Awk工作原理_分隔符_03

3.awk的格式化输出

  • print函数

data|awk '{print "Month: "}' $2 "\nYear: " $NF
awk -F: '{print "username is:" $1 "\t uid is:" $3}' /etc/passwd

  • printf函数:精确控制输出格式

%-15s:表示第1个字段占15个字符,-表示左对齐,s表示字符串
,表示OFS变量的默认值
awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}' /etc/passwd

%s字符类型
%d数值类型
%f浮点类型

- 表示左对齐。默认死右对齐
- printf默认不会在行尾自动换行,加\n

4.awk模式和动作

  • 任何awk语句都由模式和动作组成。
    模式部分决定动作语句何时触发及触发事件。处理即对数据进行的操作。
    如果省略模式部分,动作将时刻保持执行状态。
    模式可以是任何条件语句或者复合语句或者正则表达式。
    模式包括2个特殊字段BEGIN和END,使用BEGIN语句设置计数和打印头。
    BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据输入文本开始执行。
    END语句用来在awk完成文本浏览动作后,打印输出文本总数和结尾状态。
  • 模式可以是:

匹配记录整行:
$0表示整行,~表示正则匹配,!表示不匹配
awk '/^alice/' /etc/passwd 等价于awk '$0 ~ /^alice/' /etc/passwd
awk '!/alice/' /etc/passwd

匹配字段:匹配操作符~,!~
awk -F: '$1 ~ /^alice/' /etc/passwd
不是以bash结尾
awk -F: '$NF !~/bash$/' /etc/passwd

  • 比较表达式
    (1)比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。
    比较表达式使用关系运算符,用于比较数字与字符串"XXXXX"。
    (2)关系运算符

awk -F: '$3 == 0' /etc/passwd
awk -F: '$3 < 10' /etc/passwd
awk -F: '$NF == "/bin/bash"' /etc/passwd 字符串匹配,要完全一样
awk -F: '$1 ~ /alic/' /etc/passwd 模式匹配,可以匹配alice,alices
df -P|grep '/'|awk '$4 > 25000'


条件表达式
awk -F: '{if(){}}' /etc/passwd
awk -F: '{if(){} else{}}' /etc/passwd
大于300的打印整行
awk -F: '{if($3>300){print $0}}' /etc/passwd 大于300的打印整行
awk -F: '{if($3>300){print $3} else{print $1}}' /etc/passwd

算数运算:可以在模式中执行计算,awk都将按照浮点数方式执行算数运算
awk -F: '{if($3*10 > 500){print $0}}' /etc/passwd

逻辑操作符和复合模式
&& 逻辑与
|| 逻辑或
! 逻辑非
awk -F: '$1~/root/ && $3<=15' /etc/passwd
awk -F: '$1~/root/ || $3<=15' /etc/passwd

范围模式:从哪到哪
awk '/Tom/,/Suzanne/' filename

  • eg例子:

awk '/west/' datafile   匹配west
awk '/^north/' datafile 匹配north开头
awk '$3 ~ /^north/' datafile $3匹配不是以north开头的
awk '/^(no|so)/' datafile 打印整行以no或者so开头的
awk '{print $3,$2}' datafile OFS=空格
awk '{print $3 $2}' datafile 挨在一起

awk '{print $0}' /etc/passwd 整行
awk '{print "Number of fields:"NF}' /etc/passwd 字段数量,变量不带$
awk '/northeast/{print $3,$2}' datafile 满足/northeast/才print
awk '/E/' datafile 只要带有E就打印

awk '/^[ns]/{print $1}' datafie 以n或者s开头才print
awk '$5 ~ /\.[7-9]+/' datafile 匹配.7到9的1到多个
awk '$2 !~ /E/{print $1,$2}' datafile $2不匹配E,才print
awk '$3 ~ /^Joel/{print $3 "is anice boy."}' datafile $3匹配/^Joel/才print
awk '$8 ~ /[0-9][0-9]$/{print $8}' datafile /[0-9][0-9]$/表示以数字结尾

awk '$4 ~ /Chin$/{print "The price is $" $8 "."}' datafile 匹配Chin结尾的才print,$8代表第8列
awk '/Tj/{print $0}' datafile 匹配Tj才print

awk '{print $1}' /etc/passwd 打印整行,因为默认分隔是空格和tab
awk -F: '{print $1}' /etc/passwd 打印第一列

awk -F"[ :]" '{print NF}' /etc/passwd 以空格或者:分隔
111 222::yy
结果是:一根木头据两段,切1次,数空格和:数量即可,最后+1
print 4


awk '$7 == 5' datafile 数字
awk '$2 == "CT" {print $1,$2}' datafile 字符串
awk '$7 != 5' datafile

  • eg:

awk '$7 < 5 {print $4,$7}' datafile    就是 {if($7 < 5){print $4,$7}}
awk '$2 == "NW" || $1 ~ /south/ {print $1,$2}' datafile 条件1或条件2满足,才print

awk '$3 == "Chris"{ $3= "Christian";print $0}' datafile 赋值运算符
awk '/Derek/{$8+=12;print $8}' datafile //$8+=12等价于$8=$8+12

5.awk脚本编程

  • 条件判断

awk -F":" 'BEGIN{} {} END{}' passwd
只保留行处理,所以是:
awk -F":" '{}' passwd

格式:
{if(表达式){语句;语句;......}}
awk -F: '{if($3>0 && $3<1000){i++}} END{print i}' /etc/passwd 统计系统用户数

格式:
{if(表达式){语句} else{语句}}
awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数:"count;print "系统用户数:"i}}' /etc/passwd /etc/passwd

格式:
{if(表达式){语句} else if(表达式){语句} else if(表达式){语句} else {语句}}
awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i;print k;print j}}' /etc/passwd

  • 循环

行处理之前
awk 'BEGIN{i=1;while(i<=10){print i;i++}}'

行处理
awk -F: '{/^root/{i=1;while(i<=7){print $i;i++}}}' passwd

(11.1)Awk工作原理_正则表达式_04


(11.1)Awk工作原理_分隔符_05

cat b.txt
111 222
333

awk '{i=1;while(i<=NF){print $i;i++}}' b.txt 分别打印每行的每列,print默认会换行
111
222
333

C风格
awk 'BEGIN{for(i=1;i<=NF;i++){print $i}}' b.txt
111
222
333


举报

相关推荐

0 条评论