Linux 第28,29天 awk

Linux 第28,29天 awk

时间: 20180816

时间: 20180817


awk

运行方式

awk基本用法

awk的变量(内置变量和自定变量)

awk的输出命令print, printf

awk的操作符

PATTERN模式

常用的ACTION

控制语句

数组

awk容易出错的地方


awk是文本处理三剑客之一,其具有过程式编程语言,还支持条件判断,数组,循环等编程语言中

可以使用的功能。



运行方式

1. 命令行执行

awk 

2. awk程序文件

awk -f /path/awk_script

3. awk脚本

#!/bin/awk -f


awk基本用法 awk [options] 'program' fiel1 file2...

program: PATTERN{ACTION STATEMENT}

PATTERN 模式

ACTION STATEMENT动作语句,可以是多个语够组成,各语句间使用分号分隔

如print; printf


option

-F[] 指明输入字段的分隔符,默认为空格

-v VAR_NAME=VALUE 变量赋值

-f /PATH/AWK_SCRIPT 指定awk脚本文件


awk在处理文件时也是一次读取一行文本,然后根据输入分隔符进行切片,切成n个片段,

然后将每一片都赋给awk内部一个变量当做值来保存,这些变量为$1,$2...一直到最后一个

,awk就可以对这些片段单独处理比如显示某一段,特定段,甚至可以对某些片段进行额外

的加工处理,统计,计数,运算等


awk的变量

内置变量

FS input Field Seperator 输入字段分隔符,默认为空白

如awk -v FS=':' '{print $1}' /etc/passwd

RS input Record Seperator 输入时的行分隔符,默认为换行符

OFS Output Field Seperator 输出时的字段分隔符,默认为空格

ORS Output Record Seperator 输出时行的分隔符,默认为换行符

NF Number of field in current record 当前行的字段数

NR Number of Records 行数,命令后跟的所有文件将统一合并记数

FNR 行数,各文件单独计数

FILENAME 当前正被awk读取的文件的文件名 

ARGC awk命令行中的参数的个数

ARGV 数组,保存了命令行参数本身

ARGV[index]

ARGV[0] ARGV[1]

自定义变量

-v VAR_name=VALUE 变量名区分字符大小写

awk -v MYVAL=test '{print MYVAL}' /etc/fstab


在program中自定义变量

awk 'BEGIN{FS=":";f1=3}{print $f1}' /etc/passwd


awk的输出命令print, printf

print

用法 print item1,item2...

item: 字符串,用引号引用

awk '{print "hello","testword"}' /etc/fstab

变量 显示变量的值,可以直接使用变量的名进行引用

print var_name

数值 无须加引号


printf

语法 printf FORMAT, item1,item2,...

要点

1.必须提供FORMAT

2.与print语句不同,printf不会自动换行,需要显式指定换行符\n

3.FORMAT中需要分别为后面的每个item指定一个格式符,否则item无法显示

  格式符: 都以%开头,后面跟单个字符

  %c 显示字符的ASCII码

  %d %i 显示字符为十进制整数

  %e %E 科学计数法显示数值

  %f 显示为浮点数

  %g %G 以科学计数法或浮点数格式显示数值

  %s 显示为字符串

  %u 显示无符号整数

  %% 显示%符号自身

修饰符 每一种格式都有一些修饰符

#[.#]

左边的# 用于指定显示宽度

右边的# 显示精度

+|-

+表示右对齐

-表示左对齐(默认)

awk -F ":" '{printf "%-15s%+15s\n",$1,$4}' /etc/passwd


awk的操作符

操作符有算术运算、字符操作符、赋值操作符、比较操作符、模式匹配操作符、逻辑操作符

条件表达式和函数调用

算术操作符: 用来实现运算如x+y,x-y,x*y,x^y,x/6,x%y

-x 负值

+x 转换为数值

echo | awk '{a=10;b=3;print a/b}'

字符操作符: 字符串连接

赋值操作符: 通常为变量赋值,赋值操作符有以下几种

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

++, --

比较操作符: 字符串或者数值的大小比较

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

模式匹配操作符: 根据右侧的模式进行匹配操作

~ 是否能由右侧指定的模式所匹配

!~ 是否不能由右侧指定模式所匹配

awk -F ':' '{if($1~/^root/){print $0}}' /etc/passwd

逻辑运算符: 进行逻辑运算

&& 与运算

|| 或运算

awk -F ':' '{if($1~/^root/||$7~/bash$/){print $0}}' /etc/passwd

条件表达式

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


awk -F ':' '{$3>=1000?UserType="CommonUser":UserType="AdminUser";

printf "%-15s%-15s%5i\n",UserType,$1,$3}' /etc/passwd

注意此为一条命令输出时需要连接起来哦

函数调用: 调用函数来进行数据处理

格式: function_name(argu1,ague2,...)

awk有很多内部函数详细可以查看man文档里,这里做个示例,不太会用,这个是可以输出

随机数的一个函数,但是如果重复运行还是原来的随机数不知道为何

awk '{printf "%f\n",rand()}' /etc/passwd

内部函数

数值函数 rand() 返回0-1之间的一个随机函数

字符串函数

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

awk 'BEGIN{i="sdlkfjleka";print length(i)}'

sub(r,s[,t]) 基于r所表示的模式来匹配字符串t中的内容,将其第一次被

匹配到的内容替换为s所表示的字符串

awk 'BEGIN{i="I am a doctor";t="am not"; print 

i,sub("am",t,i),i}'

gsub(r,s[,t]) 与sub类似前者只是第一次匹配到替换,这个是只要匹配到就替换

split(s,a[,r]) 以r为分隔符去切割字符串s, 并将切割后的结果保存至a表示的

数组中

awk '{split($0,abc,":");print abc[1]}' /etc/passwd

substr(s,i[,n])从s所表示的字符串中取子串,取法:从i表示的位置开始,取

n个字符

从第一个开始取4个字符

awk '{print substr($0,1,4)}' /etc/passwd

时间函数

strftime(format[,timestamp][,utc-flag]) 

format 格式和date +%后边的格式一样

timestamp 是一个时间从1970-01-01日到一个时间点表示为秒和date +%s

所显示的一样

utc-flag 表示时区如+8,-8

让ping命令显示时间

ping -W 1 172.20.0.1| awk '{print $0"\t"strftime("%H:%M:%S")}'


systime() 此函数专用来显示从1970-01-01 00:00:00至现在系统时间之间

所经过的秒数

ping -W 1 172.20.0.1 | awk '{ print $0"\t" 

strftime("%H%F-%H:M:%S",systime(),-8) }' (两行一条 命令)

PATTERN模式,对哪些内容进行处理

1 空格式匹配所有

2 /regular expression/ 仅将ACTION应用于能够被Regular expression所匹配到的行

awk -F ":" '/bash$/{OFS="----------";print $1,$7}' /etc/passwd

3 relational expression 关系表达式,即结果为真、假的表达式,或者其结果能类同于

  真或假的表达,一般来说,结果为非0或非空字符串即可类同为真,否则类同为假

  awk -F ":" '$3>=1000{print $1,$3}' /etc/passwd

  awk -F ":" '$1~/^root/{print $0}' /etc/passwd /etc/shadow

4 line ranges 指定匹配的行范围

startline,endline

awk -F ":" '1,10{print $1,$7}' /etc/passwd

5 BEGIN/END 两个特殊模式

BEGIN 在文件格式化操作开始之前事行执行的一次操作,通常用于输出表头或做出

一个预处理操作

END 在文件格式操作完成之后,命令退出之前执行一次操作, 通常用于输出表尾或

做出清理操作

awk -F ":" 'BEGIN{printf "%-15s%-15s%15s\n","UserType","UserName",

"UserID"}{$3>=1000?UserType="ComUser":UserType="AdmUser";printf 

"%-15s%-15s%15d\n",UserType,$1,$3}END{print "That is all User on 

this Machine"}' /etc/passwd

此四行为一条命令,需要连接起来


常用的ACTION

1 EXPRESSION 例如变量赋值

2 Control Statements 控制语句,如if while等

3 Conpound Statements 复合语句

4 Input statements

5 output statements


控制语句

if(condition){statements}[else{statements}]

while(condition){statements}

do{statements}while(condition)

for(expr1,expr2,expr3){statements}

switch(expression){case VALUE or /REGEXP/:STATEMENT;...;default:statementN}

break

continue

delete array[index]

delete array

exit[expression]


if-else

语法 if(condition){statements}[else{statements}]

awk -F ":" '{if($3>=1000){print "CU",$1,$3}else{print "AU",$1,$3}}'

/etc/passwd(和前边是一条命令)

while循环

语法 while(condition){statements}

条件为真时循环,为假时退出循环

通常用于在当前行的各个字段间进行循环

awk '{i=1;while(i<=NF){if(length($i)>=6){print $i};i++}}' /etc/issue

输出/etc/issue文档中空格隔开的大于或等于6个字符长度的字段

do-while循环

语法do{statements}while(condition)

意义和前边的类似只是他会先执行一次语句后然后再进行条件判断

for循环

语法 for(expr1,expr2,expr3){statements}

awk '{for(i=1;i<=NF;i++){if(length($i)>=6){print $i}}}' /etc/issue

  输出/etc/issue文档中空格隔开的大于或等于6个字符长度的字段

  第二种用法用于遍历数组

  for (var_name in ARRAY){print var_name,ARRAY[var_name]}

  break and continue

  break [n] 退出当前循环,n是一个数字用于指定退出几层循环

  continue 提前结束本轮循环而进入下一轮

  next 提前结束对本行文本处理,而提前进入下一行的处理操作

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


  数组

  关联数组array[index-expression]

  index-expression 可以使用任意字符

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

  若要判断数组中的某元素是否存在,要使用"index in array"的方式进行判断

  数组遍历 要遍历数组中的元素,则要使用for(var_name in array)的方式进行,此时

  var_name会遍历array的每个索引,所以,要显示数组元数的值,要使用array[var_name]


  如 统计指定文件中所有行中每个单词出现的次数

  awk '{for(i=1;i<=NF;i++)count[$i]++}END{for(s in count)print s,count[s]}'

  test.log | sort -t' ' -k2 -rn(两行为一个命令)


  统计tcp各连接状态数量

  ss -ta| awk '!/^State/{i=1;count[$i]++}END{for(s in count)print s,count

  [s]}'


  awk容易出错的地方

  1. program中字符串要尽量使用双引号,有时候单引号不认(个人感觉是C语言的原因)

  2. 出现使用{}时一次输入一对,否则输入的多了出错几率大

  3. 逻辑思维一定要强,要不然蒙哈哈


猜你喜欢

转载自blog.51cto.com/winthcloud/2161230