Linux入门——AWK命令的使用(详解)

AWK命令的使用


初始语法

作用: 按特定的条件过滤文件,以特定的格式输出文本

工作流程:
默认按照空白字符分割文本内容,内部有$1, $2变量用于标识分割的第一部分、第 二部分; 其中$0用于代表整行内容
支持通过-F选项指定分割符 逐行处理工具

格式
awk [options] ‘script’ file1 file2
awk [options] ‘pattern{action}’ file1 file2

print

[root@localhost ~]# ifconfig ens33 | sed ‐n '2p' | awk '{print $2}'

[root@localhost ~]# sed ‐n '1p' /etc/passwd | awk ‐F: '{print $1,$7}'

[root@localhost ~]# sed ‐n '1p' /etc/passwd | awk ‐F: '{print "用户 名:",$1}'

[root@localhost ~]# sed ‐n '1p' /etc/passwd | awk ‐F: '{print "用户名: ",$1,"shell名称: ",$7}'

[root@localhost ~]# rpm ‐qa | grep php | awk ‐F‐5 '{print "yum remove y",$1}' | bash

[root@localhost ~]# ps ‐elf | sed ‐n '/vim/p' | sed '$d' | awk '{print "kill", $4}' | bash

printf

格式化输出内容

printf “格式”, 内容1, 内容2, 内容3

格式

占位符 作用
%s 字符串
%d 整数
%f 浮点数

注意: printf默认没有换行, 如果需要换行,手动添加 \n

[root@localhost ~]# awk 'BEGIN{printf "%s", "hello"}' 
hello[root@localhost ~]# 
[root@localhost ~]#
[root@localhost ~]# awk 'BEGIN{printf "%d", 100}' 
100[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# awk 'BEGIN{printf "%d", 3.1415926}' 
3[root@localhost ~]# 
[root@localhost ~]# 
[root@localhost ~]# awk 'BEGIN{printf "%f", 3.1415926}'

-: 左对齐, 默认右对齐

 [root@localhost ~]# awk 'BEGIN{printf "%10s\n", "shell"}' 
          shell 
 [root@localhost ~]# awk 'BEGIN{printf "%‐10s\n", "shell"}' 
 shell
[root@localhost ~]# sed ‐n '1,3p' /etc/passwd | awk ‐F: '{printf "%‐8s%‐1 5s\n", $1, $7}'
[root@localhost ~]# df ‐hT | grep "^/" | awk '{printf "%‐10s%‐30s%‐10s%‐8 s%‐10s%‐7s\n", "磁盘名称: ", $1, "挂载点:", $7, "使用率:", $6}'

用户自定义变量

变量的定义及其调用

选项 格式
-v选项 -v 变量名称=值
[root@localhost ~]# awk ‐v name="martin" 'BEGIN{print "hello", name}' 
[root@localhost ~]# awk ‐v name="Martin" ‐v age=40 'BEGIN{print "My name is ", name, "My age is ", age}' 
[root@localhost ~]# awk 'BEGIN{name="martin"; print name}' 
[root@localhost ~]# awk 'BEGIN{print a++}'


内置变量

  • FS: 用于定义行分割符, 默认空白字符
[root@localhost ~]# sed ‐n '1p' /etc/passwd | awk ‐v OFS="‐‐‐>" ‐F: '{pri nt $1, $7}'
  • RS 用于定义awk读取多行内容时的行分割符, 默认换行符
[root@localhost ~]# sed ‐n '1,2p' /etc/passwd | awk ‐v RS=":" '{print $0}'
  • ORS用于定义awk输出多行内容时的行分割符,默认换行符
[root@localhost ~]# sed ‐n '1,2p' /etc/passwd | awk ‐v ORS="‐‐‐>" ‐F: '{p rint $1}'
  • NR 用于记录行号, 处理多个文件时,行号连续记录
[root@localhost ~]# awk '{print NR}' /etc/hosts
[root@localhost ~]# awk '{print FNR}' /etc/hosts 
[root@localhost ~]# awk '{print NR}' /etc/hosts /etc/redhat‐release
  • FNR用于记录行号, 处理多个文件时,行号单独记录
[root@localhost ~]# awk '{print FNR}' /etc/hosts /etc/redhat‐release 
[root@localhost ~]# awk 'NR==3{print $0}' /etc/passwd
  • NF 记录awk分割文件时,每行内容被分割的段数
[root@localhost ~]# awk '{print $NF}' /tmp/file01 
[root@localhost ~]# netstat ‐antp | awk '{print $NF}' 
[root@localhost ~]# df ‐hT | awk '{print $NF}'

pattern写法

分类 样例
数字表达式 +, -, *, /, %,++, --,+=
字符表达式 “ab” + “cd”=abcd
比较表达式 ==, !=, >, >=, <, <=
逻辑表达式 &&,||
[root@localhost ~]# awk ‐F: '$3>2000{print $1}' /etc/passwd 
[root@localhost ~]# awk ‐F: '$3>=1 && $3<=999{print $1}' /etc/passwd 
[root@localhost ~]# netstat ‐antp | sed '1,2d' | awk '$6=="LISTEN"{print $0}' 
[root@localhost ~]# df ‐hT | sed ‐n '/^\//p' | awk '+$6>10{print "磁盘名 称:", $1, "挂载点: ", $NF, "使用率:", $6}'
[root@localhost ~]# awk ‐F: '$7 ~ "nologin$"{print "用户名: ", $1, "sh名 称: ", $7}' /etc/passwd
  • 正则表达式
[root@localhost ~]# netstat ‐antp | awk '/^tcp/{print $0}' 
[root@localhost ~]# awk ‐F: '/nologin$/{print $1}' /etc/passwd 
[root@localhost ~]# awk ‐F: '/^(r|s)/{print $1}' /etc/passwd
  • /正则表达式1/, /正则表达式2/
[root@localhost ~]# awk '/Sep 10 09:40:42/,/Sep 10 11:01:01/{print $0}' / var/log/messages
  • BEGIN{} :在处理文本数据前,执行的操作
[root@localhost ~]# sed ‐n '1,3p' /etc/passwd | awk ‐F: 'BEGIN{print "‐‐‐ ‐内容开始‐‐‐‐‐"}{print $1,$7}'
  • END{} :在处理文本数据后, 执行的操作
[root@localhost ~]# sed ‐n '1,3p' /etc/passwd | awk ‐F: 'BEGIN{print "‐‐‐ ‐内容开始‐‐‐‐‐"}{print $1,$7}END{print "‐‐‐‐‐结束‐‐‐‐‐‐"}'

逻辑控制语句

条件判断语法

  • if (条件) {条件为真的操作}
  • if (条件) {条件为真的操作} else {条件为假的操作}
  • if (条件) {条件为真的操作} else if (条件2) {条件为真的操作}
 [root@localhost ~]# awk ‐F: '{if($3==0) {print $1, "is 管理员"} else {prin t $1, "is 普通用户"}}' /etc/passwd 
 [root@localhost ~]# awk ‐F: ‐v bash_number=0 ‐v nologin_number=0 '{if($7= ="/bin/bash") {bash_number++} else if($7=="/sbin/nologin") {nologin_number+ +}}END{print "bash用户数量:", bash_number, "nologin用户数量", nologin_numbe r}' /etc/passwd 
 [root@localhost ~]# netstat ‐antp | awk ‐v listen_number=0 '/^tcp/{if($6= ="LISTEN") {listen_number++}}END{print listen_number}' 
 [root@localhost ~]# df ‐hT | awk '/^\//{if(+$6>10) {print $1, $NF, $6}}'

循环语法

  • for(变量定义; 循环的条件; 改变循环条件的语句) {语句;语句;…}
    continue (break)
[root@localhost ~]# sed ‐n '1,2p' /etc/passwd | awk ‐F: '{for(i=1;i<=7;i+ +) {if(length($i)>4) {print $i}}}' 
[root@localhost ~]# awk '{for(i=1; i<=NF; i++) {if(length($i)>7) {print $i}}}' /tmp/file01

数组

  • 定义数组
[root@localhost ~]# awk 'BEGIN{test[1]="192.168.1.1"; test[2]="10.1.1.1"; test[3]="10.1.1.2"}'
  • 获取单个数据
[root@localhost ~]# awk 'BEGIN{test[1]="192.168.1.1"; test[2]="10.1.1.1"; test[3]="10.1.1.2"; print test[3]}' 
10.1.1.2 
[root@localhost ~]# awk 'BEGIN{test[1]="192.168.1.1"; test[2]="10.1.1.1"; test[3]="10.1.1.2"; print test[1]}' 
192.168.1.1 
[root@localhost ~]# awk 'BEGIN{test[1]="192.168.1.1"; test[2]="10.1.1.1"; test[3]="10.1.1.2"; print test[2]}'
  • 获取数组中所有数据
[root@localhost ~]# awk 'BEGIN{test[1]="192.168.1.1"; test[2]="10.1.1.1"; test[3]="10.1.1.2"; for(i=1;i<=3;i++) {print test[i]}}'
[root@localhost ~]# awk 'BEGIN{test[1]="192.168.1.1"; test[2]="10.1.1.1"; test[3]="10.1.1.2"; for(i=1;i<=length(test);i++) {print test[i]}}'
  • 数组支持以任何数据作为下标使用
[root@localhost ~]# awk 'BEGIN{test["martin"]="bj"; test["robin"]="hb"; t est["lz"]="hb"}' 
[root@localhost ~]# awk 'BEGIN{test["martin"]="bj"; test["robin"]="hb"; t est["lz"]="hb"; print test["robin"]}' 
通过for循环获取数组中的数据 
[root@localhost ~]# awk 'BEGIN{test["martin"]="bj"; test["robin"]="hb"; t est["lz"]="hb"; for(i in test) {print i}}' 
[root@localhost ~]# awk 'BEGIN{test["martin"]="bj"; test["robin"]="hb"; t est["lz"]="hb"; for(i in test) {print test[i]}}' 
[root@localhost ~]# awk 'BEGIN{test["martin"]="bj";
[root@localhost ~]# awk ‐F: '{test[$7]++}END{for(i in test) {print i, tes t[i]}}' /etc/passwd 
[root@localhost ~]# netstat ‐antp | awk '/^tcp/{test[$6]++}END{for(i in t est) {print i, test[i]}}'

统计web的UV量

[root@localhost ~]# awk '{user_count[$1]++}END{for(ip in user_count) {pri nt ip, user_count[ip]}}' /var/log/httpd/access_log | sort ‐r ‐n ‐k2

统计PV量

[root@localhost ~]# awk '{page_count[$7]++}END{for(i in page_count) {prin t i, page_count[i]}}' /var/log/httpd/access_log | sort ‐r ‐n ‐k 2

统计某天的访问量

[root@localhost ~]# grep "10/Sep/2020" /var/log/httpd/access_log | wc ‐l

awk内置函数

  • length() :获取字符串的长度

  • int( ):返回整数

[root@localhost ~]# awk 'BEGIN{print int(12.9)}' 12
  • index():返回字符所在字符串中的位置
[root@localhost ~]# awk 'BEGIN{print index("abcd","b")}' 2
  • substr(string,start [,length]):取string字符串中的子串,从start开始,取length个;start从1开始计数
[root@localhost ~]# awk 'BEGIN{str="this is test"; print substr(str,2,5)}' his i
  • match(字符串,子串):检测str中是否含有"is" 如果有,则返回"is"第一次出现的位置,如果没有则返回0
[root@localhost ~]# awk 'BEGIN{str="This is a test"; print match(str,"is")}'
  • tolower(string):将string中的所有字母转为小写
[root@localhost ~]# awk 'BEGIN{print tolower("Kello")}' kello
  • toupper(string):将string中所有字母转换为大写
[root@localhost ~]# awk 'BEGIN{print toupper("hello")}' HELLO

你可能感兴趣的:(大学课程知识,Linux入门,linux,运维,容器,centos)