笔记·linux三剑客

grep:文本过滤工具

-i:忽略大小写;
-o:仅显示匹配到的字符串本身;
-v:反选,显示没有匹配到的行;
-E:支持扩展正则;
-q:静默模式;
-B n:前n行
-A n:后n行
-C n:前后各n行

sed:流编辑器,文本编辑工具

常用选项:

-n 不输出模式空间内容到屏幕,即不自动打印
-e 多点编辑
-f FILE 从指定文件中读取编辑脚本
-r, -E 使用扩展正则表达式
-i.bak 备份文件并原处编辑
-s 将多个文件视为独立文件,而不是单个连续的长文件流
#说明:
  -ir 不支持
  -i -r 支持
  -ri 支持
  -ni 会清空文件

地址格式:

1. 不给地址:对全文进行处理
2. 单地址:
  #:指定的行,$:最后一行
  /pattern/:被此处模式所能够匹配到的每一行
3. 地址范围:
  #,# #从#行到第#行,3,6 从第3行到第6行
  #,+# #从#行到+#行,3,+4 表示从3行到第7行
  /pat1/,/pat2/
  #,/pat/
  /pat/,#
4. 步进:~
  1~2 奇数行
  2~2 偶数行

命令:

p 打印当前模式空间内容,追加到默认输出之后
Ip 忽略大小写输出
d 删除模式空间匹配的行,并立即启用下一轮循环
a [\]text 在指定行后面追加文本,支持使用\n实现多行追加
i [\]text 在行前面插入文本
c [\]text 替换行为单行或多行文本
w file 保存模式匹配的行至指定文件
r file 读取指定文件的文本至模式空间中匹配到的行后
= 为模式空间中的行打印行号
! 模式空间中匹配行取反处理
q 结束或退出sed

查找替代:

s/pattern/string/修饰符 查找替换,支持使用其它分隔符,可以是其它形式:s@@@,s###
修饰符:
  g 行内全局替换
  p 显示替换成功的行
  w /PATH/FILE 将替换成功的行保存至文件中
  I,i 忽略大小写

范例:

#ifconfig eth0 | sed -n '2p'
#sed -n "$(echo $[`cat /etc/passwd|wc -l`-1])p" /etc/passwd    #打印倒数第二行
#seq 10 | sed -n '3,$p'    #第三行到结束
#sed -e '2d' -e '4d' seq.log
#sed '2d;4d' seq.log
#sed '/^#/d;/^$/d' /etc/httpd/conf/httpd.conf    #不显示注释行和空行
#grep -Ev '^#|^$' /etc/httpd/conf/httpd.conf
#sed -n '/^#/!p' fstab    #显示非注释行
#sed -Ei.bak '/^GRUB_CMDLINE_LINUX/s/(.*)(")$/\1 net.ifnames=0\2/' /etc/default/grub
#sed -nr 's/r..t/&er/gp' /etc/passwd
#df | sed -En '/^\/dev\/sd/s@.* ([0-9]+)%.*@\1@p'
#sed -n '/^$/=' file 显示空行行号    #显示空行行号
#sed -n 's/root/&superman/p' /etc/passwd #单词后
#ifconfig eth0 | sed -n '2s/^.*inet //;s/ netmask.*//p'    #获取ip地址
#echo /etc/sysconfig/ | sed -rn 's#(.*)/([^/]+)/?#\1#p'    #取目录名
#echo /etc/sysconfig/ | sed -rn 's#(.*)/([^/]+)/?#\2#p'    #取基名
#echo a.b.c.gz |sed -En 's/(.*)\.([^.]+)$/\1/p'   #取前缀
#echo a.b.c.gz |sed -En 's/(.*)\.([^.]+)$/\2/p'    #取后缀
#echo a.b.c.gz |grep -Eo '.*\.'    #取前缀
#echo a.b.c.gz |grep -Eo '[^.]+$'    #取后缀
#echo a.b.tar.gz | sed -rn 's@.*\.([^.]+)\.([^.]+)$@\1.\2@p'    #取后缀
#sed -nr '/^GRUB_CMDLINE_LINUX/s/"$/ net.ifnames=0"/p' /etc/default/grub    #修改内核参数
#sed -rn '/^GRUB_CMDLINE_LINUX=/s@(.*)"$@\1 net.ifnames=0"@p' /etc/default/grub
#sed -rn '/^GRUB_CMDLINE_LINUX=/s@"$@ net.ifnames=0"@p' /etc/default/grub
#sed -r '/^(#|$)/d' /etc/httpd/conf/httpd.conf    #过滤掉空行和注释行
#sed -n '/^$/d;/^[[:space:]]*#/!p' /etc/httpd/conf/httpd.conf    #排掉空行和多个空格加井号的行

sed高级用法:

P 打印模式空间开端至\n内容,并追加到默认输出之前
h 把模式空间中的内容覆盖至保持空间中
H 把模式空间中的内容追加至保持空间中
g 从保持空间取出数据覆盖至模式空间
G 从保持空间取出内容追加至模式空间
x 把模式空间中的内容与保持空间中的内容进行互换
n 读取匹配到的行的下一行覆盖至模式空间
N 读取匹配到的行的下一行追加至模式空间
d 删除模式空间中的行
D 如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环。

范例:

sed -n 'n;p' FILE
seq 10 | sed 'N;s/\n//'
sed '1!G;h;$!d' FILE
seq 10 | sed -n '/3/{g;1!p;};h' #前一行
seq 10 | sed -nr '/3/{n;p}' #后一行
sed 'N;D'FILE
seq 10 |sed '3h;9G;9!d'
sed '$!N;$!D' FILE
sed '$!d' FILE
sed 'G' FILE
sed 'g' FILE
sed '/^$/d;G' FILE
sed 'n;d' FILE
sed -n '1!G;h;$p' FILE

awk:文本报告生成器

常见选项

-F “分隔符” 指明输入时用到的字段分隔符,默认的分隔符是若干个连续空白符
-v var=value 变量赋值

awk控制语句

{ statements;… } 组合语句
if(condition) {statements;…}
if(condition) {statements;…} else {statements;…}
while(conditon) {statments;…}
do {statements;…} while(condition)
for(expr1;expr2;expr3) {statements;…}
break
continue
exit

动作 print

#awk '{print "hello,awk"}'
#awk '{print 2*3}'
#awk -F: '{print $1,$3}' /etc/passwd
#awk '{print $1}' access_log |sort |uniq -c|sort -nr|head
#df | awk '{print $1,$5}' #取出分区利用率
#df | awk -F"[[:space:]]+|%" '{print $5}'
#df | awk -F'[[:space:]]+|%' '/^\/dev\/sd/{print $1,$5}'
#df|awk -F' +|%' '/^\/dev\/sd/{print $1,$5}'
#ifconfig eth0 | awk '/netmask/{print $2}' #取ip地址
#ifconfig eth0 |awk -F " +|:" '/Mask/{print $4}'

awk内部变量

FS:输入字段分隔符,默认为空白字符,功能相当于 -F;
  #awk -v FS=':' '{print $1,FS,$3}' /etc/passwd
  #awk -v FS=":" '{print $1FS$3}' /etc/passwd
  #awk –F: '{print $1,$3,$7}' /etc/passwd
  #S=:;awk -v FS=$S '{print $1FS$3}' /etc/passwd
OFS:输出字段分隔符,默认为空白字符
  #awk -v FS=':' '{print $1,$3,$7}' /etc/passwd|head -n1
  #awk -v FS=':' -v OFS=':' '{print $1,$3,$7}' /etc/passwd|head -n1
RS:输入记录record分隔符,指定输入时的换行符
  #awk -v RS=' ' '{print }' /etc/passwd
ORS:输出记录分隔符,输出时用指定符号代替换行符
  #awk -v RS=' ' -v ORS='###' '{print $0}' /etc/passwd
NF:字段数量
  #awk -F:'{print NF}' /etc/fstab
  #awk -F:'{print $(NF-1)}' /etc/passwd
  #ls /misc/cd/BaseOS/Packages/*.rpm |awk -F"." '{print $(NF-1)}'|sort |uniq -c

  连接数最多的前3个ip:
  #awk -F" +|:" '{print $(NF-2)}' ss.log |sort |uniq -c|sort -nr|head -n3
  #awk -F" +|:" '/^ESTAB/{print $(NF-2)}' ss.log |sort |uniq -c|sort -nr|head -n3
  #ss -nt |grep "^ESTAB" | awk -F"[[:space:]]+|:" '{print $(NF-2)}
  #ss -nt |awk -F"[[:space:]]+|:" '/^ESTAB/{print $(NF-2)}'
  #ss -nt|awk -F: '{print $(NF-1)}' |awk '/^[0-9]/{print $NF}'|sort |uniq -c |head -n 3
  #awk -F' +|:' 'NR!=1{print $(NF-2)}' ss.log|sort |uniq -c

  每十分钟检查将连接数超过100个以上的IP放入黑名单拒绝访问:
  LINK=100
  while true;do
    ss -nt | awk -F"[[:space:]]+|:" '/^ESTAB/{print $(NF-2)}'|sort |uniq -c|while read count ip;do
      if [ $count -gt $LINK ];then
        iptables -A INPUT -s $ip -j REJECT
      fi
    done
  done

NR:记录行的编号
  #awk '{print NR,$0}' /etc/issue /etc/centos-release
  #ifconfig eth0 | awk '/netmask/{print $2}'
  #ifconfig eth0 | awk 'NR==2{print $2}'
  #awk -F: 'END{print NR}' /etc/passwd
  #awk -F: 'BEGIN{print NR}' /etc/passwd
FNR:各文件分别计数,记录的编号
  #awk '{print FNR}' /etc/fstab /etc/inittab
  #awk '{print NR,$0}' /etc/issue /etc/redhat-release
  #awk '{print FNR,$0}' /etc/issue /etc/redhat-release
FILENAME:当前文件名
  #awk '{print FNR,FILENAME,$0}' /etc/issue /etc/redhat-release
ARGC:命令行参数的个数
  #awk '{print ARGC}' /etc/issue /etc/redhat-release
  #awk 'BEGIN{print ARGC}' /etc/issue /etc/redhat-release
ARGV:数组,保存的是命令行所给定的各参数,每一个参数:ARGV[0],......
  #awk 'BEGIN{print ARGV[0]}' /etc/issue /etc/redhat-release
  #awk 'BEGIN{print ARGV[1]}' /etc/issue /etc/redhat-release

awk自定义变量:-v var=value 或 在program中直接定义

#awk -v test1=test2="hello,gawk" 'BEGIN{print test1,test2}' #test1="test2=hello,gawk",test2=''
#awk -v test1=test2="hello1,gawk" 'BEGIN{test1=test2="hello2,gawk";print test1,test2}' #test1和test2都等于“hello1,gawk”
#awk -F: '{sex="male";print $1,sex,age;age=18}' /etc/passwd
#awk -v test='hello gawk' 'BEGIN{print test}'
#awk 'BEGIN{test="hello,gawk";print test}'
#cat awkscript
  {print script,$1,$2}
  #awk -F: -f awkscript script="awk" /etc/passwd

动作 printf:printf “FORMAT”, item1, item2, ...

%s:显示字符串
%d, %i:显示十进制整数
%f:显示为浮点数
%e, %E:显示科学计数法数值
%c:显示字符的ASCII码
%g, %G:以科学计数法或浮点形式显示数值
%u:无符号整数
%%:显示%自身
#[.#] 第一个数字控制显示的宽度;第二个#表示小数点后精度,如:%3.1f
- 左对齐(默认右对齐) 如:%-15s
+ 显示数值的正负符号 如:%+d

范例:
  awk -F: '{printf "%s",$1}' /etc/passwd
  awk -F: '{printf "%s\n",$1}' /etc/passwd
  awk -F: '{printf "%20s\n",$1}' /etc/passwd
  awk -F: '{printf "%-20s\n",$1}' /etc/passwd
  awk -F: '{printf "%-20s %10d\n",$1,$3}' /etc/passwd
  awk -F: '{printf "Username: %s\n",$1}' /etc/passwd
  awk -F: '{printf “Username: %sUID:%d\n",$1,$3}' /etc/passwd
  awk -F: '{printf "Username: %25sUID:%d\n",$1,$3}' /etc/passwd
  awk -F: '{printf "Username: %-25sUID:%d\n",$1,$3}' /etc/passwd

操作符

算术操作符:
x+y, x-y, x*y, x/y, x^y, x%y
-x:转换为负数
+x:将字符串转换为数值

赋值操作符:
=, +=, -=, *=, /=, %=, ^=,++, --
范例:
  #awk 'BEGIN{i=0;print i++,i}'
  #awk 'BEGIN{i=0;print ++i,i}'

比较操作符:
==, !=, >, >=, <, <=
范例:
  #awk 'NR==2' /etc/issue
  #awk -F: '$3>=1000' /etc/passwd
  #seq 10 | awk 'NR%2==0' #偶数行
  #seq 10 | awk 'NR%2==1' #奇数行
  #seq 10 | awk 'NR%2!=0 #奇数行

模式匹配符:
~ 左边是否和右边匹配,包含关系
!~ 是否不匹配
范例:
  #awk -F: '$0 ~ /root/{print $1}' /etc/passwd
  #awk -F: '$0 ~ "^root"{print $1}' /etc/passwd
  #awk '$0 !~ /root/' /etc/passwd
  #awk '/root/' /etc/passwd
  #df | awk -F"[[:space:]]+|%" '$0 ~ /^\/dev\/sd/{print $5}'

逻辑操作符:
与:&&,并且关系
或:||,或者关系
非:!,取反
范例:
  #awk -F: '$3>=0 && $3<=1000 {print $1,$3}' /etc/passwd
  #awk -F: '$3==0 || $3>=1000 {print $1,$3}' /etc/passwd
  #awk -F: '!($3==0) {print $1,$3}' /etc/passwd
  #awk -F: '!($3>=500) {print $1,$3}' /etc/passwd

条件表达式(三目表达式):
selector?if-true-expression:if-false-expression
范例:
  #awk -F: '{$3>=1000?usertype="Common User":usertype="SysUser";printf "%-20s:%12s\n",$1,usertype}' /etc/passwd

模式PATTERN:PATTERN:根据pattern条件,过滤匹配的行,再做处理

/regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
  #awk '/^UUID/{print $1}' /etc/fstab
  #awk '!/^UUID/{print $1}' /etc/fstab
  #df | awk '/^\/dev\/sd/'

relational expression: 关系表达式,结果为“真”才会被处理
  真:结果为非0值,非空字符串
  假:结果为空字符串或0值
  #seq 10 | awk '" "' #真
  #seq 10 | awk 'magedu' #假
  #seq 10 | awk '"magedu"' #真
  #seq 10 | awk '0' #假
  #seq 10 | awk '1' #真
  #seq 10 | awk -v magedu="abc" 'magedu' #真
  #seq 10 | awk -v magedu="" 'magedu' #假
  范例:
  #seq 10 | awk 'i=0'
  #seq 10 | awk 'i=1'
  #seq 10 | awk 'i=!i'
  #seq 10 | awk '{i=!i;print i}'
  #seq 10 | awk '!(i=!i)'
  #seq 10 | awk -v i=1 'i=!i'
  #awk -F: '$3>=1000{print $1,$3}' /etc/passwd
  #awk -F: '$3<1000{print $1,$3}' /etc/passwd
  #awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd
  #awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd

line ranges:行范围
  不支持直接用行号,但可以使用变量NR间接指定行号
  /pat1/,/pat2/ 不支持直接给出数字格式
  范例:
  #seq 10 | awk 'NR>=3 && NR<=6'
  #awk 'NR>=3 && NR<=6{print NR,$0}' /etc/passwd
  #sed -n '3,6p' /etc/passwd
  #awk '/^bin/,/^adm/' /etc/passwd
  #sed -n '/^bin/,/^adm/p' /etc/passwd

BEGIN/END模式
  BEGIN{}:仅在开始处理文件中的文本之前执行一次
  END{}:仅在文本处理完成之后执行一次
  范例:
  #awk -F: 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "END FILE"}'/etc/passwd
  #awk -F: '{print "USER USERID";print $1":"$3} END{print "END FILE"}' /etc/passwd
  #awk -F: 'BEGIN{print "USER UID \n--------------- "}{print $1,$3}' /etc/passwd
  #awk -F: 'BEGIN{print "USER UID \n--------"}{print $1,$3}END{print"=========="}' /etc/passwd
  #awk -F: 'BEGIN{printf "--------------------------------\n%-20s|%10s|\n--------------------------------\n","username","uid"}{printf"%-20s|%10d|\n--------------------------------\n",$1,$3}' /etc/passwd

条件判断 if-else

  if(condition1){statement1}else if(condition2){statement2}else if(condition3){statement3}......else {statementN}
  范例:
  #awk -F: '{if($3>=1000)print $1,$3}' /etc/passwd
  #awk -F: '{if($3<=100){print "<=100",$3}else if ($3<=1000){print "<=1000",$3}else{print ">=1000",$3}}' /etc/passwd
  #awk -F: '{if($NF=="/bin/bash") print $1}' /etc/passwd
  #awk '{if(NF>5) print $0}' /etc/fstab
  #awk -F: '{if($3>=1000) {printf "Common user: %s\n",$1} else {printf "root or Sysuser: %s\n",$1}}' /etc/passwd
  #awk -F: '{if($3>=1000) printf "Common user: %s\n",$1; else printf "root or Sysuser: %s\n",$1}' /etc/passwd
  #df -h|awk -F% '/^\/dev\/sd/{print $1}'| awk '$NF>=80{print $1,$5}'
  #df | awk -F"[[:space:]]+|%" '/^\/dev\/sd/{if($5>80)print $1,$5}'
  #df | awk -F' +|%' '/^\/dev\/sd/{if($5>=10)print $1,$5}'
  #awk 'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
  #df | awk -F'[ %]+' '/\/dev\/.d./{if($5>=10){print $1,$5}}'
  #df | awk -F' +|%' '/^\/dev\/sd/{if($5>=10)print $1,$5}'
  #df | awk -F'[[:space:]]+|%' '/^\/dev\/sd/{if($5>=10)print$1,$5}'
  #df | awk -F"[ %]+" '/^\/dev\/sd/{if($(NF-1)>10)print $(NF-1)"full";else {print $(NF-1)" OK"}}'
  #df | awk -F"[ %]+" '/^\/dev\/sd/{if($(NF-1)>10){print $(NF-1)"full"}else {print $(NF-1)" OK"}}'

条件判断 switch

  switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}

循环 while

  while (condition) {statement;…}
  范例:
  #awk -v i=1 -v sum=0 'BEGIN{while(i<=100){sum+=i;i++};print sum}'
  #内置函数length()返回字符数,而非字节数
  #awk 'BEGIN{print length("hello")}'
  #awk 'BEGIN{print length("马哥教育")}'
  #awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){print $i,length($i); i++}}' /etc/grub2.cfg
  #awk '/^[[:space:]]*linux16/{i=1;while(i<=NF){if(length($i)>=10){print $i,length($i)}; i++}}' /etc/grub2.cfg
  #awk 'BEGIN{ total=0;i=1;while(i<=100){total+=i;i++};print total}'

循环 do-while

  do {statement;…}while(condition)
  范例:
  #awk 'BEGIN{ total=0;i=1;do{ total+=i;i++;}while(i<=100);print total}'

循环 for

  for(expr1;expr2;expr3) {statement;…}
  for(variable assignment;condition;iteration process) {for-body} #常见用法
  for(var in array) {for-body} #能够遍历数组中的元素
  范例:
  #awk 'BEGIN{sum=0;for(i=1;i<=100;i++){sum+=i};print sum}'
  #for((i=1,sum=0;i<=100;i++));do let sum+=i;done;echo $sum
  #awk 'BEGIN{total=0;for(i=1;i<=100;i++){total+=i};print total}'
  #awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
  性能比较:
  time (awk 'BEGIN{ total=0;for(i=0;i<=10000;i++){total+=i;};print total;}')
  time (total=0;for i in {1..10000};do total=$(($total+i));done;echo $total)
  time (for ((i=0;i<=10000;i++));do let total+=i;done;echo $total)
  time (seq –s ”+” 10000|bc)

continue 和 break

#awk 'BEGIN{for(i=1;i<=100;i++){if(i==50)continue;sum+=i};print sum}'
#awk 'BEGIN{for(i=1;i<=100;i++){if(i==50)break;sum+=i};print sum}'
#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i%2==0)continue;sum+=i}print sum}'
#awk 'BEGIN{sum=0;for(i=1;i<=100;i++){if(i==50)break;sum+=i}print sum}'

next

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

数组

array_name[index-expression]
weekdays["mon"]="Monday"
范例:
  #awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
  #awk '!line[$0]++' dupfile
  #awk '{print !line[$0]++, $0, line[$0]}' dupfile
  #awk '{!line[$0]++;print $0, line[$0]}' dupfile

判断数组索引是否存在:
  #awk 'BEGIN{array["i"]="x"; array["j"]="y" ; print "i" in array, "y" in array }'
  #awk 'BEGIN{array["i"]="x"; array["j"]="y" ;if ("i" in array ){print "存在"}else{print "不存在"}}'
  #awk 'BEGIN{array["i"]=

若要遍历数组中的每个元素:
  for(var in array) {for-body
  #awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays){print i,weekdays[i]}}'
  #awk 'BEGIN{students[1]="daizong";students[2]="junzong";students[3]="kunzong";for(xin students){print x":"students[x]}}'
  #awk -F: '{user[$1]=$3}END{for(i in user){print "username:"i,"uid: "user[i]}}' /etc/passwd

显示主机的连接状态出现的次数:
  #awk 'NR!=1{print $1}' ss.log |sort |uniq -c
  #cat ss.log | sed -nr '1!s/^([^0-9]+) .*/\1/p'|sort |uniq -c
  #ss -ant | awk 'NR!=1{state[$1]++}END{for(i in state){print i,state[i]}}'
  #netstat -tan | awk '/^tcp/{state[$NF]++}END{for(i in state){print i,state[i]}}'
  #awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' /var/log/httpd/access_log
  #awk '{ip[$1]++}END{for(i in ip){print ip[i],i}}' access_log |sort -nr| head -3
  #awk '{ip[$1]++}END{for(i in ip){print i,ip[i]}}' access_log |sort -k2 -nr|head -3

封掉查看访问日志中连接次数超过1000次的IP:
  #awk '{ip[$1]++}END{for(i in ip){if(ip[i]>=1000){system("iptables -A INPUT -s "i" -j REJECT")}}}' nginx.access.log-20200428

多维数组:
  #awk 'NR!=1{if($2=="m"){m_sum+=$3;m_num++}else{f_sum+=$3;f_num++}}END{print "男生平均成绩="m_sum/m_num,"女生平均成绩="f_sum/f_num}' score.txt
  # awk 'NR!=1{score[$2]+=$3;num[$2]++}END{for(i in score){print i,score[i]/num[i]}}' score.txt
  # awk 'NR!=1{score[$2]+=$3;num[$2]++}END{for(i in score){if(i=="m"){print "男生平均成绩=",score[i]/num[i]}else{print "女生平均成绩=",score[i]/num[i]}}}' score.txt

awk 函数

https://www.gnu.org/software/gawk/manual/gawk.html#Functions

数值处理:
rand():返回0和1之间一个随机数
srand():配合rand() 函数,生成随机数的种子
int():返回整数
#awk 'BEGIN{srand();print rand()}'
#awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100)}'

字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串搜索r表示模式匹配的内容,并将第一个匹配内容替换为s
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,
#cut -d: -f1 /etc/passwd | awk '{print length()}'
#awk -F: '{print length($1)}' /etc/passwd
#echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
#echo "2008:08:08 08:08:08" | awk '{sub(/:/,"-",$1);print $0}'
#echo "2008:08:08 08:08:08" | awk 'gsub(/:/,"-",$0)'
#echo "2008:08:08 08:08:08" | awk '{gsub(/:/,"-",$0);print $0}'
#netstat -tn | awk '/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){print i,count[i]}}'

可以awk中调用shell命令:
system('cmd') 空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来
#awk 'BEGIN{system("hostname")}'
#awk 'BEGIN{score=100; system("echo your score is " score) }'
#netstat -tn | awk '/^tcp/{split($5,ip,":");count[ip[1]]++}END{for(i in count){if(count[i]>=10){system("iptables -A INPUT -s "i" -j REJECT")}}}'

时间函数:
systime() 当前时间到1970年1月1日的秒数
strftime() 指定时间格式
#awk 'BEGIN{print systime()}'
#awk 'BEGIN{print strftime("%Y-%m-%dT%H:%M",systime()-3600)}'

自定义函数:
function name ( parameter, parameter, ... ) {
  statements
  return expression
}
范例:
  #cat func.awk
  function max(x,y) {
    x>y?var=x:var=y
    return var
  }
  BEGIN{print max(a,b)}
  #awk -v a=30 -v b=20 -f func.awk

awk 脚本

将awk程序写成脚本,直接调用或执行
#cat passwd.awk
{if($3>=1000)print $1,$3}
#awk -F: -f passwd.awk /etc/passwd

posted @ 2022-07-25 17:36  Krill_ss  阅读(74)  评论(0编辑  收藏  举报