shell中的awk

awk工作模式简介

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

语法格式

1
2
awk 'BEGIN{}pattern{commands}END{}' file_name
standard output | awk 'BEGIN{}pattern{commands}END{}'

语法格式解释

语法格式 解释
BEGIN{} 正式处理数据之前执行
pattern 匹配模式
{commands} 处理命令,可能多行
END{} 处理完所有匹配数据后执行

awk中的内置变量

内置变量 含义
$0 整行内容
$1-$n 当前行的第1-n个字段
NF 当前行的字段个数,也就是有多少列
NR 当前行的行号,从1开始计数
FNR 多文件处理时,每个文件行号单独计数,都是从0开始
FS 输入字段分隔符。不指定默认以空格或tab分割
RS 输入行分隔符。默认回车换行
OFS 输出字段分隔符。默认为空格
ORS 输出行分隔符,默认为回车换行
FILENAME 当前输入的文件名字
ARGC 命令行参数个数
ARGV 命令行参数数组

printf的格式说明符

格式符 含义
%s 打印字符串
%d 打印十进制数字
%f 打印浮点数
%x 打印十六进制数
%o 打印八进制数
%e 打印数学的科学计数法形式
%c 打印单个字符的ASCII码
- 左对齐
+ 右对齐
# 显示8进制在前面加0,显示16进制在前面加0x

关系运算匹配

关系运算符 含义
~ 匹配正则表达式
!~ 不匹配正则表达式

字符串函数对照表

函数名 解释 函数返回值
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其他选项

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

测试脚本

假如有文本test.txt如下:

1
2
3
4
5
root     pts/1   192.168.1.100  Tue Feb 10 11:21   still logged in
root pts/1 192.168.1.100 Tue Feb 10 00:46 - 02:28 (01:41)
root pts/1 192.168.1.100 Mon Feb 9 11:41 - 18:30 (06:48)
dmtsai pts/1 192.168.1.100 Mon Feb 9 11:41 - 11:41 (00:00)
root tty1 Fri Sep 5 14:09 - 14:10 (00:01)

展示第一列:

1
awk '{print $1}'

显示/etc/passwd的账户(以:分隔)

1
cat /etc/passwd | awk -F ':' '{print $1}'

如果显示账户和账户对应的shell

1
cat /etc/passwd | awk -F ':' '{print $1"\t"$7}'

显示列头列尾

1
cat /etc/passwd |awk  -F ':'  'BEGIN {print "name,shell"}  {print $1","$7} END {print "blue,/bin/nosh"}'

执行结果:

1
2
3
4
5
6
7
name,shell
root,/bin/bash
daemon,/bin/sh
bin,/bin/sh
sys,/bin/sh
....
blue,/bin/nosh

打印行号和列数

1
cat /etc/passwd |awk  -F ':'  'BEGIN {count=0;print "name\t\tshell"}  {count=count+1;print count":"$1"\t\t"$7} END {print "count=", count}'

打印nologin的用户展示行号和列数

1
cat /etc/passwd |awk  -F ':'  'BEGIN {count=0;print "name\t\tshell"} /nologin/ {count=count+1;print count":"$1"\t\t"$7} END {print "count=", count}'