GNU awk

栏目: 服务器 · 发布时间: 8年前

内容简介:GNU awk

文本处理三工具:grep, sed, awk

grep, egrep, fgrep :文本过滤工具; pattern

sed: 行编辑器

模式空间、保持空间

awk :报告生成器,格式化文本输出;

AWK: Aho, Weinberger, Kernighan –> New AWK, NAWK

GNU awk, gawk 

gawk – pattern scanning and processing language

基本用法: gawk [options] ‘program’ FILE …

program: PATTERN{ACTION STATEMENTS}

语句之间用分号分隔

print, printf

选项:

-F :指明输入时用到的字段分隔符;

-v var=value: 自定义变量;

1 print  

print item1, item2, …

要点:

(1) 逗号分隔符;

(2) 输出的各 item 可以字符串,也可以是数值;当前记录的字段、变量或 awk 的表达式;

(3) 如省略 item ,相当于 print $0;

例一:显示文件倒数 5 行 ,显示第 2 4 ,个字符

[root@MiWiFi-R3L-srv ~]# tail -5 /etc/fstab | awk '{print $2,$4}'

例二:省略item显示整行

[root@MiWiFi-R3L-srv ~]# tail -5 /etc/fstab | awk '{print}'
/dev/mapper/VolGroup-lv_swap swap                    swap    defaults        0 0
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0 

2 、变量

2.1 内建变量

FS input field seperator ,默认为空白字符;

例一:定义FS 变量为:

[root@MiWiFi-R3L-srv ~]# awk -v FS=':' '{print $1}' /etc/passwd 

OFS output field seperator ,默认为空白字符;

例一:定义变量

[root@MiWiFi-R3L-srv ~]# awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd 

RS input record seperator ,输入时的换行符;

ORS output record seperator ,输出时的换行符;

NF number of field ,字段数量

{print NF}, {print $NF}

例一:查看字符个数

[root@MiWiFi-R3L-srv ~]# awk '{print NF}' /etc/fstab 

NR number of record, 行数;

例一:显示行数

[root@MiWiFi-R3L-srv ~]# awk '{print NR}' /etc/fstab
1
2
3
4 

FNR :各文件分别计数;行数;

FILENAME :当前文件名;

例一:显示当前文件名

[root@localhost ~]# awk '{print FILENAME}' /etc/fstab
/etc/fstab
/etc/fstab

ARGC :命令行参数的个数;

[root@localhost ~]# awk '{print ARGC}' /etc/fstab

ARGV :数组,保存的是命令行所给定的各参数;

2.2 自定义变量

(1) -v var=value

变量名区分字符大小写;

例一: -v 定义变量

[root@localhost ~]# awk -v test='hello gawk' '{print test}' /etc/fstab
hello gawk
hello gawk

(2) program 中直接定义

[root@localhost ~]# awk 'BEGIN{test="hello gawk ";print test}'
hello gawk 

3 printf 命令  

格式化输出: printf FORMAT, item1, item2, … 

(1) FORMAT 必须给出 ;

(2) 不会自动换行,需要显式给出换行控制符, \n

(3) FORMAT 中需要分别为后面的每个 item 指定一个格式化符号;

格式符:

%c: 显示字符的 ASCII 码;

%d, %i: 显示十进制整数;

%e, %E: 科学计数法数值显示;

%f :显示为浮点数;

%g, %G :以科学计数法或浮点形式显示数值;

%s :显示字符串;

%u :无符号整数;

%%: 显示 % 自身;

例一:显示每一行命令的第一个字符,以字符串显示

[root@localhost ~]# awk -F: '{printf "%s",$1}' /etc/passwd

例二:显示每一行命令的用户名

[root@localhost ~]# awk -F: '{printf "Username: %s\n",$1}' /etc/passwd 

修饰符:

#[.#] :第一个数字控制显示的宽度;第二个 # 表示小数点后的精度;

%3.1f

-: 左对齐

+ :显示数值的符号

例一:显示控制宽度15

[root@localhost ~]# awk -F: '{printf "Username: %s\n",$1}' /etc/passwd 

4 、操作符  

算术操作符:

x+y, x-y, x*y, x/y, x^y, x%y

-x

+x: 转换为数值;

字符串操作符:没有符号的操作符,字符串连接

赋值操作符:

=, +=, -=, *=, /=, %=, ^=

++, —

比较操作符:

>, >=, <, <=, !=, ==

模式匹配符:

~ :是否匹配

!~ :是否不匹配

逻辑操作符:

&&

||

!

函数调用:

function_name(argu1, argu2, …)

条件表达式:

selector?if-true-expression:if-false-expression

例一:条件表达式

[root@localhost ~]# awk -F: '{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}' /etc/passwd 

5 PATTERN  

(1) empty :空模式,匹配每一行;

(2) /regular expression/ :仅处理能够被此处的模式匹配到的行;

regular expression 正责表达式

例一:输出能匹配的行

[root@localhost ~]# awk  '/^UUID/{print $1}' /etc/fstab 

(3) relational expression: 关系表达式;结果有“真”有“假”;结果为“真”才会被处理;

真:结果为非 0 值,非空字符串;

例一:为 “真”才处理

[root@localhost ~]# awk -F: '$3>=1000 {print $1,$3}' /etc/passwd
nfsnobody 65534 

(4) line ranges :行范围,

startline,endline /pat1/,/pat2/

例一:以h 开关 u 结局的字符

[root@localhost ~]# awk -F: '/^h/,/^u/{print $1}' /etc/passwd

例一:大于等于2 行小于等于 10

[root@localhost ~]# awk -F: '(NR>=2&&NR<=10){print $1}' /etc/passwd 

注意: 不支持直接给出数字的格式

~]# awk -F: ‘(NR>=2&&NR<=10){print $1}’ /etc/passwd

(5) BEGIN/END 模式

BEGIN{}: 仅在开始处理文件中的文本之前执行一次;

END{} :仅在文本处理完成之后执行一次;

6 、常用的 action  

(1) Expressions

(2) Control statements if, while 等;

(3) Compound statements :组合语句;

(4) input statements

(5) output statements

7 、控制语句  

if(condition) {statments}

if(condition) {statments} else {statements}

while(conditon) {statments}

do {statements} while(condition)

for(expr1;expr2;expr3) {statements}

break

continue

delete array[index]

delete array

exit

{ statements }

7.1 if-else

语法: if(condition) statement [else statement]

例一:查看大等于 100 的用户名称

[root@localhost ~]# awk -F: '{if ($3>=100) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
root or Sysuser: root
root or Sysuser: bin
root or Sysuser: daemon
root or Sysuser: adm
root or Sysuser: lp

例二:if 语句判断

[root@localhost ~]# awk -F: '{if ($3>=100) print $1,$3}' /etc/passwd

例三:显示字符数大于5 个的

[root@localhost ~]# awk -F: '{if ($NF>5) print $0}' /etc/fstab
UUID=d928b19c-a5b3-4b6d-918c-2952b6353c69 /boot                   ext4    defaults        1 2
tmpfs                   /dev/shm                tmpfs   defaults        0 0
devpts                  /dev/pts                devpts  gid=5,mode=620  0 0

使用场景:对 awk 取得的整行或某个字段做条件判断;

7.2 while 循环

语法: while(condition) statement

条件 “真”,进入循环;条件“假”,退出循环; 

使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用;

例一:while 循环显示每一行个数

[root@localhost ~]# awk '/^[[:space:]]*kernel/{i=1;while(i<=NF) {print $i,length($i); i++}}' /etc/grub.conf
kernel 6
/vmlinuz-2.6.32-71.el6.x86_64 29
ro 2
root=/dev/mapper/VolGroup-lv_root 33
rd_LVM_LV=VolGroup/lv_root 26
rd_LVM_LV=VolGroup/lv_swap 26 

~]# awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF) {print $i,length($i); i++}}’ /etc/grub2.cfg

~]# awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)}; i++}}’ /etc/grub2.cfg

7.3 do-while 循环

语法: do statement while(condition)

意义:至少执行一次循环体

7.4 for 循环

语法: for(expr1;expr2;expr3) statement

for(variable assignment;condition;iteration process) {for-body}

例一:历用for 循环显示个行的字符数

[root@localhost ~]# awk '/^[[:space:]]*kernel/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub.conf
kernel 6
/vmlinuz-2.6.32-71.el6.x86_64 29
ro 2
root=/dev/mapper/VolGroup-lv_root 33

特殊用法:

能够遍历数组中的元素;

语法: for(var in array) {for-body}

7.5 switch 语句

语法: switch(expression) {case VALUE1 or /REGEXP/: statement; case VALUE2 or /REGEXP2/: statement; …; default: statement} 

7.6 break continue

break [n]

continue

7.7 next

提前结束对本行的处理而直接进入下一行;

例一:不符合条件就直接进入下一行

~]# awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd

8 array

关联数组: array[index-expression] 

index-expression:

(1) 可使用任意字符串;字符串要使用双引号;

(2) 如果某数组元素事先不存在,在引用时, awk 会自动创建此元素,并将其值初始化为“空串”;

若要判断数组中是否存在某元素,要使用 “index in array” 格式进行;

weekdays[mon]=”Monday”

若要遍历数组中的每个元素,要使用 for 循环;

for(var in array) {for-body}

~]# awk ‘BEGIN{weekdays[“mon”]=”Monday”;weekdays[“tue”]=”Tuesday”;for(i in weekdays) {print weekdays[i]}}’

注意: var 会遍历 array 的每个索引;

state[“LISTEN”]++

state[“ESTABLISHED”]++

~]# netstat -tan | awk ‘/^tcp\>/{state[$NF]++}END{for(i in state) { print i,state[i]}}’

~]# awk ‘{ip[$1]++}END{for(i in ip) {print i,ip[i]}}’ /var/log/httpd/access_log

练习 1 :统计 /etc/fstab 文件中每个文件系统类型出现的次数;

[root@localhost ~]# awk '/^UUID/{fs[$3]++}END{for(i in fs){print i,fs[i]}}' /etc/fstab
ext4 1 

9 、函数  

9.1 内置函数

数值处理:

rand() :返回 0 1 之间一个随机数;

字符串处理:

length([s]) :返回指定字符串的长度;

sub(r,s,[t]) :以 r 表示的模式来查找 t 所表示的字符中的匹配的内容,并将其第一次出现替换为 s 所表示的内容;

gsub(r,s,[t]) :以 r 表示的模式来查找 t 所表示的字符中的匹配的内容,并将其所有出现均替换为 s 所表示的内容;

split(s,a[,r]) :以 r 为分隔符切割字符 s ,并将切割后的结果保存至 a 所表示的数组中;

~]# netstat -tan | awk ‘/^tcp\>/{split($5,ip,”:”);count[ip[1]]++}END{for (i in count) {print i,count[i]}}’

9.2 自定义函数

sed awk


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

GWT in Action

GWT in Action

Robert Hanson、Adam Tacy / Manning Publications / 2007-06-05 / USD 49.99

This book will show Java developers how to use the Google Web Toolkit (GWT) to rapidly create rich web-based applications using their existing skills. It will cover the full development cycle, from ......一起来看看 《GWT in Action》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

html转js在线工具
html转js在线工具

html转js在线工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具