shell之awk

2019-07-28  本文已影响0人  IT小池

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

语法格式:
第一种形式:awk 'BGGIN{}pattern{commands}END{}' file_name
第二种形式:standard output | awk 'BGGIN{}pattern{commands}END{}' file_name
说明:
BEGIN{} 正式处理数据之前执行
pattern{} 匹配模式
{commands} 处理命令,可能多行
END{} 处理完所有匹配数据后执行

awk选项

选项 说明
-v 参数传递
-f 指定脚本文件
-F 指定分隔符
-V 查看awk版本号

如:

# -v
[root@VM_0_14_centos test]# num=10
[root@VM_0_14_centos test]# var=20
[root@VM_0_14_centos test]# awk -v num1="$num" -v num2="$var" 'BEGIN{print num1,num2}'
# -f
[root@VM_0_14_centos test]# num=10
[root@VM_0_14_centos test]# var=20
[root@VM_0_14_centos test]# awk -v num1="$num" -v num2="$var" -f test.awk
# -F
[root@VM_0_14_centos test]# awk -F ":" '{print $1}' /etc/passwd

注:在引用变量的时候,最好加双引号""

内置变量

$0 整行内容

[root@VM_0_14_centos test]# awk '{print $0}' test.txt

$1-$n 当前行的第 1 - n 个字段(默认 冒号: / tab键 切割)

[root@VM_0_14_centos test]# awk '{print $2}' test.txt

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

[root@VM_0_14_centos test]# awk '{print NF}' test.txt

输出每行中最大的字段(一列)$NF

[root@VM_0_14_centos test]# awk '{print $NF}' test.txt

NR 当前行的行号,从 1 开始计数

[root@VM_0_14_centos test]# awk '{print NR}' test.txt

FNR 多文件处理时,每个文件行号单独计数,都是从 0 开始

[root@VM_0_14_centos test]# awk '{print FNR}' test.txt

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

[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"}{print $0}' test.txt

RS 输入行分隔符,默认回车换行

[root@VM_0_14_centos test]# awk 'BEGIN{RS="--"}{print $0}' test.txt

OFS 输出字段(列)分隔符,默认为空格

[root@VM_0_14_centos test]# awk 'BEGIN{FS=":";OFS='&'}{print $1,$2}' test.txt

ORS 输出行分隔符,默认为回车换行

[root@VM_0_14_centos test]# awk 'BEGIN{FS=":";OFS="&";ORS="@"}{print $1,$2}' test.txt

FILENAME 当前输入的文件名字

[root@VM_0_14_centos test]# awk '{print FILENAME}' test.txt

ARGC 命令行参数个数

[root@VM_0_14_centos test]# awk '{print ARGC}' test.txt

ARVG 命令行参数数组

printf

printfprint都是输出,只不过,print有默认的分隔符(空格 / tab键),而printf没有默认的分割符,且还能美化输出(如:左对齐 / 右对齐)

printf格式说明符:
%s 打印字符串

[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%-20s %-20s\n",$1,$7}' test.txt

说明:%20s:是占20个字符,在20字符后再输出第二个字段值 $7;且两个 %s 之间有空格,表示输出的两个字段 $1 $7直接以空格间隔。\n是一次完整的输出后,回车换行显示第二次完整输出。减号(-) 是左对齐显示输出
%d 打印十进制数
%f 打印一个浮点数
%x 打印打印十六进制数
%o 打印八进制数
%e 打印数字的科学计数法形式
%o 打印单个字符的 ASCLL码

printf格式修饰符:
- 左对齐
+ 右对齐
# 显示8进制或16进制在前面加 #
示例:

  1. 以字符串格式打印 test.txt 中的第7个字段,以 : 作为分隔符
[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%s\n",$7}' test.txt
  1. 以10进制格式打印 test.txt 中的第3个字段,以 : 作为分隔符
[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%d\n",$3}' test.txt
  1. 以浮点数格式打印 test.txt 中的第3个字段,以 : 作为分隔符
[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%0.2f\n",$3}' test.txt

说明:0.2 是保留2位小数

  1. 以16进制格式打印 test.txt 中的第3个字段,以 : 作为分隔符
[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%#x\n",$3}' test.txt

说明:# 显示8进制或16进制在前面加 #

  1. 以8进制格式打印 test.txt 中的第3个字段,以 : 作为分隔符
[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%#o\n",$3}' test.txt
  1. 以科学计数法格式打印 test.txt 中的第3个字段,以 : 作为分隔符
[root@VM_0_14_centos test]# awk 'BEGIN{FS=":"} {printf "%e\n",$3}' test.txt

awk匹配模式

1. RegExp

如:1. 匹配 /etcpasswd 文件行中含有 root 字符串的所有行

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}/root/{print $0}' /etc/passwd

如:2. 匹配 /etcpasswd 文件行中以 root 开头的所有行

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}/^root/{print $0}' /etc/passwd
2. 运算符匹配
  1. 关系运算符
运算符 说明
< (小于)
> (大于)
<= (小于等于)
>= (大于等于)
== (等于)
!= (不等于)
~ (匹配正则表达式)
!= (不匹配正则表达式)

如:1. 匹配 /etc/passwd 文件中第 3 个字段(数值)小于50的所有行信息

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}$3<50{print $0}' /etc/passwd

如:2. 匹配 /etc/passwd 文件中第 7 个字段为 /bin/bash 的所有行信息

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}$7=="/bin/bash"{print $0}' /etc/passwd
  1. 布尔运算符匹配
运算符 说明
||
&&
!

如:1. 匹配 /etc/passwd 文件中包含 sync 或 root 的所有行信息

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}$1=="root" || $1=="sync"{print $0}' /etc/passwd

如:2. 匹配 /etc/passwd 文件中第3个字段小于50 且第 4 个字段大于50的所有行信息

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}$3<50 && $4>50{print $0}' /etc/passwd
  1. 动作表达式中的 算术运算符
运算符 说明
+
-
*
/
%
^ 或 ** 乘方
++x 在返回 x 变量之前,x 变量加1
x++ 在返回 x 变量之后,x 变量加1

如:

# 加 +
// num2未定义就是 0
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2+=num1;print num1,num2}'
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;print num1+num2}'
# 减 -
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;print num1-num2}'
# 乘 *
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;print num1*num2}'
# 除 /
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;print num1/num2}'
// %0.2f 保留两位小数
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;printf "%0.2f\n",num1/num2}'
# 模 %
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;print num1%num2}'
# 乘方 ^ 或 ** 
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=30;print "%0.2f\n",num1**num2}'
# ++x
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=++num1;print num1,num2}'
# x++
[root@VM_0_14_centos /]# awk 'BEGIN{num1=20;num2=num1++;print num1,num2}'

如:统计 test.txt 文件中的空白行数量

[root@VM_0_14_centos /]# awk '/^$/{total++}END{print total}' /test.txt
3. awk动作中的条件及循环:

如:判断 test.txt 文件中第三列数字大于50且小于100的行

[root@VM_0_14_centos /]# awk 'BEGIN{FS=":"}{if($3>50 && $3<100) print $0}' /test.txt

awk中的字符串函数:

函数名 解释 函数返回值
length(str) 计算字符串长度 整数长度值
index(str1,str2) 在str1中查找str2的位置 返回值为位置索引,从1计数
tolower(str) 转换为小写 转换后的小写字符串
toupper(str) 转换为大写 转换后的大写字符串
substr(str,m,n) 从str的m个字符开始,截取n位 截取后的子串
split(str,arr,fs) 按fs切割字符串,结果保存arr 切割后的子串的个数
match(str,RE) 在str中按照RE查找,返回位置 返回索引位置
sub(RE,RepStr,str) 在str中搜索符合RE的字串,将其替换为RepStr,只替换第一个 替换的个数
gsub(RE,RepStr,str) 在str中搜索符合RE的字串,将其替换为RepStr,替换所有 替换的个数

注:awk中的下标是从 1 开始,shell中下标是从 0 开始
如:1.以 : 为分隔符,返回 /etc/passwd 中的每行中每个字段的长度:
新建文件 test.awk(后缀是.awk),新手不熟悉先这样新建文件写,内容如下

BEGIN  {
    FS=":"
}
{
    i=1
    while(i <= NF){ # NF 当前行的字段个数,也就是有多少列
        if(i == NF)
              printf "%d",length($i)
         else
              printf "%d:",length($i)
    }
     print "" # print 输出默认就是空格换行
}

执行的时候,输入命令 awk -f test.awk /etc/passwd-f是指引入文件

上一篇 下一篇

猜你喜欢

热点阅读