Linux文本处理之awk

awk是一个文本处理工具,通常用于处理数据并生成结果报告

一、awk的工作模式

语法格式:

1、awk 'BEGIN{}pattern{commands}END{}' file_name

2、standard output | awk 'BEGIN{}pattern{command}END{}'

BEGIN{} 正式处理数据之前执行

pattern 匹配模式

{commands} 处理命令,可能多行

END{} 处理完所有匹配数据后执行

二、awk的内置变量

内置变量含义

$0 整行内容

$1-$n 当前行的第1-n个字段

NF 当前行的字段个数,也就是有多少列(Number Field)

NR 当前行的行号,从1开始计数(Number Row)

FNR 多文件处理时,每个文件行号单独计数,都是从1开始(File Number Row)

FS 输入字段分隔符,不指定默认以空格或tab键分割(Field Separator)

RS 输入行分隔符,默认回车换行 ((Row Separator)

OFS 输出字段分隔符,默认空格(Output Field Separator)

ORS 输出行分隔符,默认为回车换行(Output Row Separator)

FILENAME 当前输入的文件名字

ARGC 命令行参数个数

ARGV 命令行参数数组

例:

awk 'BEGIN{FS=":"}{print $7}' passwd(以:为分割符)等价于 awk 'BEGIN{FS=":"}{print $NF}' passwd

awk '{print NF}' passwd

awk '{print NR}' passwd

awk '{print NR}' passwd sed.txt

awk '{print FNR}' passwd sed.txt

awk 'BEGIN{RS="--";FS="|";ORS="&";OFS="@@"}{print $1,$3}' list(实际工作中不常用)

三、awk格式化输出之printf

%s 打印字符串

%d 打印十进制数

- 左对齐

+ 右对齐

#  打印8进制前面加0或16进制前面加0x

例:

awk 'BEGIN{FS=":"}{printf "%s ",$1}' passwd

awk 'BEGIN{FS=":"}{printf "%-20s %-20s ",$1,$7}' passwd

四、awk模式匹配的两种用法

第一种模式匹配:RegExp 按正则表达式匹配

第二种模式匹配:关系运算匹配 按关系运算匹配

例:

1、RegExp

awk 'BEGIN{FS=":"}/root/{printf $0}' passwd(常量字符串)

awk 'BEGIN{FS=":"}/^mail/{print $0}' passwd(正则表达式)

2、运算符匹配

关系运算符匹配

< 小于

> 大于

<= 小于等于

>= 大于等于

== 等于

!= 不等于

~ 匹配正则表达式

!~ 不匹配正则表达式

awk 'BEGIN{FS=":"}$3>50{print $0}' passwd

awk 'BEGIN{FS=":"}$3==1{print $0}' passwd

awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' passwd

awk 'BEGIN{FS=":"}$7!="/bin/bash"{print $0}' passwd

#以:为分隔符,匹配/etc/passwd中第3个字段包含3个以上数字的所有行信息

awk 'BEGIN{FS=":"}$3~/[0-9]{3,}/{print $0}' passwd

awk 'BEGIN{FS=":"}$1~/root/{print $0}' passwd

awk 'BEGIN{FS=":"}$1=="root"{print $0}' passwd

awk 'BEGIN{FS=":"}$0~//bin/bash/{print $0}' passwd

awk 'BEGIN{FS=":"}$0!~//bin/bash/{print $0}' passwd

布尔运算符匹配

|| 或

&& 与

! 非

awk 'BEGIN{FS=":"}$1=="ftp"||$1=="mail"{print $0}' passwd

awk 'BEGIN{FS=":"}$3<50&&$4>50{print $0}' passwd

awk 'BEGIN{FS=":"}$3<50&&$7~//bin/bash/{print $0}' passwd

五、awk中表达式的用法

运算符 含义

+ 加

- 减

* 乘

/ 除

% 模

^或** 乘方

++x 在返回x变量之前,x变量加1

x++ 在返回x变量之后,x变量加1

例:

awk 'BEGIN{num1=20;num2+=num1;print num1,num2}'

#匹配文件中的空白行

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

六、awk动作中的条件及循环

if(条件表达式)

    动作1

else if(条件表达式)

    动作2

else

    动作3

例1:

awk 'BEGIN{FS=":"}{if($3>50&&$3<100)print $0}' passwd

例2:

vim scripts.awk(编写awk脚本)

BEGIN{
FS=":"
}
{
if($3<50)
{
printf "%-20s%-20s%-5d ","小于50的UID",$1,$3
}
else if($3>50 && $3<100)
{
printf "%-20s%-20s%-5d ","大于50且小于100的UID",$1,$3
}
else
{
printf "%-20s%-20s%-5d ","大于100的UID",$1,$3
}
}

执行命令:awk -f scripts.awk passwd

循环语句-while

while(条件表达式)

    动作

循环语句-do while

do

    动作

while(条件表达式)

循环语句-for

for(初始化计数器;测试计数器;计数器变更)

    动作

例1:

vim while.awk

BEGIN{
while(i<=100)
{
sum+=i
i++
}
print sum
}

awk -f while.awk

例2:

vim for.awk

BEGIN{
for(i=0;i<=100;i++)
{
sum+=i
}
print sum
}

awk -f for.awk

例3:

vim dowhile.awk

BEGIN{
do
{
sum+=i
i++
}
while(i<=100)
print sum
}

awk -f dowhile.awk

七、awk中的字符串函数

length(str) 计算字符串长度

index(str1,str2) 在str1中查找str2的位置

tolower(str) 转化为小写

toupper(str) 转化为大写

substr(str,m,n) 从str的m个字符开始,截取n位

split(str,arr,fs) 按fs分割符切割字符串,结果保存arr数组(awk中的数组下标从1开始),函数返回切割后的子串个数

match(str,RE) 在str中按照RE正则表达式查找,返回索引位置

sub(RE,RepStr,str) 在str中搜索符合RE的子串,将其替换为RepStr,只替换一个,函数返回替换的个数

gsub(RE,RepStr,str)  在str中搜索符合RE的子串,将其替换为RepStr,替换所有,函数返回替换的个数

# 将第一个数字串替换为$

awk 'BEGIN{str="aaa 123 bbb 456 ccc789";count=sub(/[0-9]+/,"$",str);print count,str}'

#将所有数字串替换为$

awk 'BEGIN{str="aaa 123 bbb 456 ccc789";count=gsub(/[0-9]+/,"$",str);print count,str}' 

、awk中的常用选项

-v 参数传递

-f 指定脚本文件

-F 指定分隔符

-V 查看awk的版本

例1:

num1=20
var="kafka"
awk -v num2="$num1" -v var1="$var" 'BEGIN{print num2,var1}'

例2:

num1=20 

var="kafka"

vim test.awk

BEGIN{print num2,var1}

awk -v num2="$num1" -v var1="$var" -f test.awk

例3:

vim test2.awk

BEGIN{
  str="aaa 123 bbb 456 ccc789"
  count=sub(/[0-9]+/,"$",str)
  print count,str
}

awk -f test2.awk

例4:

awk 'BEGIN{FS=":"}{print $7}' passwd(以:为分割符)

等价于awk -F ":" '{print $7}' passwd

、awk中数组的用法

shell中数组的用法:(数组下标从0开始)

array=("a" "b" "c" "d" "e")

打印元素:echo ${array[2]}

打印所有元素:echo ${array[@]}

打印元素个数:echo ${#array[@]}    echo ${#array[*]}

打印元素长度:echo ${#array[3]}

给元素赋值:array[3]="cc"

删除元素:unset array[3](删除元素后,原来的元素依旧使用原来的下标)

删除所有元素:unset array

分片访问:echo ${array[@]:1:3}(从下标为1的元素开始访问3个元素)

元素内容替换:echo ${array[@]/e/E}(只替换元素第一个e)echo ${array[@]//e/E} (替换所有的e)

数组的遍历:for a in ${array[@]};do echo $a;done

for a in ${array[@]}

do

  echo $a

done

awk中数组的用法:(数组下标从1开始)

awk 'BEGIN{str="hadoop spark yarn storm flume";split(str,array," ");for(i=1;i<=length(array);i++){print array[i]}}'

awk的数组中可以使用字符串作为数组的下标

awk 'BEGIN{array["var1"]="zhangsan";array["var2"]="lisi";array["var3"]="wangwu";for(i in array){print array[i]}}'

例:统计各种tcp状态连接状态数

netstat -an | grep tcp | awk '{array[$6]++}END{for(i in array){print i,array[i]}}'

原文地址:https://www.cnblogs.com/xiaoxianxianxian/p/12669103.html