@mrz1
2018-01-04T09:03:46.000000Z
字数 14196
阅读 885
笔记
格式化输出:printf "FORMAT", item1, item2, ...
(1) 必须指定FORMAT
(2) 不会自动换行,需要显式给出换行控制符,\n
(3) FORMAT中需要分别为后面每个item指定格式符
格式符:与item一一对应
%c: 显示字符的ASCII码
%d, %i: 显示十进制整数
%e, %E:显示科学计数法数值(10的几次方)
%f:显示为浮点数
%g, %G:以科学计数法或浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%: 显示%自身
修饰符:
#[.#]:第一个数字控制显示的宽度;第二个#表示小数点后精度,%3.1f
-: 左对齐(默认右对齐)%-15s
+:显示数值的正负符号%+d
awk -F: '{printf "%s",$1}' /etc/passwd //不换行显示user
awk -F: '{printf "%s\n",$1}' /etc/passwd //换行显示user
[root@centos7 ~]#awk -F: '{printf "Username:%s\n",$1}' /etc/passwd
Username:root
Username:bin
Username:daemon
[root@centos7 ~]#awk -F: '{printf "username:%s|uid:%d\n",$1,$3}' /etc/passwd
username:root|uid:0
username:bin|uid:1
username:daemon|uid:2
[root@centos7 ~]#awk -F: '{printf "%-30s|%10d\n",$1,$3}' /etc/passwd //正数右对齐负数左对齐
root |0
bin |1
daemon |2
[root@centos7 ~]#awk -v n=123.456789 'BEGIN{printf "%9.4f",n}'
123.4568 //有一个空格
n是9位数1-9;保留四位123.4568(约等于)宽度九位 所以前面是一个空格
[root@centos7 ~]#awk -v n=123.456789 'BEGIN{printf "%9.5f",n}'
123.45679 //没有空格
n是9位数1-9;保留五位123.45679(约等于)宽度九位 所以前面没有空格
[root@centos7 ~]#awk -v n=123.456789 'BEGIN{printf "%9.2f",n}'
123.46 //有三个个空格
n是9位数1-9;保留二位123.46(约等于)宽度九位 所以前面是三个空格
算术操作符
x+y, x-y, x*y, x/y, x^y, x%y
-x: 转换为负数
+x: 转换为数值
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:
=, +=, -=, *=, /=, %=, ^=
++, --
下面两语句有何不同
[root@centos7 ~]#awk 'BEGIN{i=0;print ++i,i}'
1 1
[root@centos7 ~]#awk 'BEGIN{i=0;print i++,i}'
0 1
实例:
[root@centos7 ~]#awk -v m=10 -v n=2 'BEGIN{printf m/n}'
5
[root@centos7 ~]#awk -v m=10 -v n=2 'BEGIN{printf m-n}'
8
[root@centos7 ~]#awk -v m=10 -v n=2 'BEGIN{printf m^n}'
100
[root@centos7 ~]#awk -v m=10 -v n=3 'BEGIN{printf m%n}' 取模
1
[root@centos7 ~]#awk -v m=10 -v n=3 'BEGIN{printf m*=n}'
30
比较操作符:
==, !=, >, >=, <, <=
模式匹配符:
~:左边是否和右边匹配包含
!~:是否不匹配
示例:
awk -F: '$0 ~ /root/{print $1}' /etc/passwd //查看包含root的行
[root@centos7 ~]#awk '$0~"^bin" {print $1}' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@centos7 ~]#awk '$0~"^root"' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@centos7 ~]#awk '$0~"^bin"' /etc/passwd
bin:x:1:1:bin:/bin:/sbin/nologin
[root@centos7 ~]#awk '$0 ~ /^(root|bin)/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
awk '$0 !~ /root/' /etc/passwd //不包含root
[root@centos7 ~]#awk -F: '$3==0' /etc/passwd
root:x:0:0:root:/root:/bin/bash
[root@centos7 ~]#awk -F: '$3>=1000' /etc/passwd
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
fei:x:1000:1000:fei:/home/fei:/bin/bash
lili:x:1001:1001::/home/lili:/bin/bash
""或者// 里面的表示正则
[root@centos7 ~]#awk -F: 'i' /etc/issue
[root@centos7 ~]#awk -F: -v i=0 'i' /etc/issue
[root@centos7 ~]#awk -F: -v i="" 'i' /etc/issue
[root@centos7 ~]#awk -F: -v i=" " 'i' /etc/issue
The hostname is \n
time is \t
tty is \l
\S
Kernel \r on an \m
注意:i只要有值就打印(0,"" 未定义不包括在内)
逻辑操作符:与&&,或||,非!
示例:
awk -F: '$3>=0 && $3<=1000 {print $1}' /etc/passwd
[root@centos7 ~]#awk -F: '$3>=0 && $3<=1 {print $1}' /etc/passwd
root
bin
awk -F: '$3==0 || $3>=1000 {print $1}' /etc/passwd
[root@centos7 ~]#awk -F: '$3==0 || $3<=2 {print $1}' /etc/passwd
root
bin
daemon
awk -F: '!($3==0){print $1}' /etc/passwd
[root@centos7 ~]#awk -F: '!($3!=0){print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
awk -F: '!($3>=500) {print $3}' /etc/passwd //找出userUID小于500的uid
打印末尾是/bin/bash
[root@centos7 ~]#awk -F: '$NF == "/bin/bash" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
fei:x:1000:1000:fei:/home/fei:/bin/bash
[root@centos7 ~]#awk -F: '$0 ~ "/bin/bash" {print $0}' /etc/passwd
root:x:0:0:root:/root:/bin/bash
fei:x:1000:1000:fei:/home/fei:/bin/bash
[root@centos7 ~]#awk 'BEGIN{i=0;print !i++,i}'
1 1
[root@centos7 ~]#awk 'BEGIN{i=0;print !(i++),i}'
1 1
[root@centos7 ~]#awk 'BEGIN{i=2;print !i++,i}'
0 3
[root@centos7 ~]#awk 'BEGIN{i=-1;print !++i,i}'
1 0
[root@centos7 ~]#awk 'BEGIN{i=0;print !++i,i}'
0 1
注意 ()不起作用
函数调用:function_name(argu1, argu2, ...)
条件表达式(三目表达式):
selector?if-true-expression:if-false-expression
示例:
[root@centos7 ~]#awk -F: '{$3>=1000?usertype="Common User":usertype="SysUser";printf "%-20s|%-s\n",$1,usertype}' /etc/passwd
root |SysUser
bin |SysUser
daemon |SysUser
[root@centos7 ~]#awk -F: '{$3>=1000?usertype="Common User":usertype="SysUser";printf "%-20stype:%s\n",$1,usertype}' /etc/passwd
root type:SysUser
bin type:SysUser
daemon type:SysUser
adm type:SysUser
PATTERN:根据pattern条件,过滤匹配的行,再做处理
(1) 如果未指定:空模式,匹配每一行
(2) /regular expression/:仅处理能够模式匹配到的行,需要用/ /括起来
awk '/^UUID/{print $1}' /etc/fstab //打印UUID的那几行
awk'!/^UUID/{print $1}' /etc/fstab //不打印UUID的那几行
awk '/^#/' /etc/profile //打印以#开头的
awk '!/^#/' /etc/profile //不打印以#开头的
(3) relational expression: 关系表达式,结果为"真"才会被处理
真:结果为非0值,非空字符串
假:结果为空字符串或0值
示例:
awk -F: 'i=1;j=1{print i,j}' /etc/passwd //每一行后加 1 1
awk '!0' /etc/passwd 取反为真,打印
awk '!1' /etc/passwd 取反为假,不打印
awk -F: '$3>=1000{print $1,$3}' /etc/passwd uid大于1000的打印
awk -F: '$3<1000{print $1,$3}' /etc/passwd uid小于1000的打印
awk -F: '$NF=="/bin/bash"{print $1,$NF}' /etc/passwd 打印结尾为/bin/bash的
awk -F: '$NF ~ /bash$/{print $1,$NF}' /etc/passwd 打印结尾为bash的
seq 10 | awk 'i=!i' 打印奇数行seq 10 |sed -n ''1~2p
seq 10 | awk -v i=1 'i=!i' 打印偶数行seq 10 |sed -n ''2~2p
seq 10|awk '!(i=!i)' 打印偶数行
[root@centos7 ~]#awk 'i=!i {print NR,$0}' /etc/passwd
1 root:x:0:0:root:/root:/bin/bash
3 daemon:x:2:2:daemon:/sbin:/sbin/nologin
5 lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
(4) line ranges:行范围
startline,endline:/pat1/,/pat2/不支持直接给出数字格式
awk -F: '/^root\>/,/^nobody\>/{print $1}' /etc/passwd //root到nobody直接的 包括nobody
awk -F: '(NR>=1&&NR<=3){print NR,$1}' /etc/passwd //1-3行
seq 10 |sed -n '2,4p'
(5) BEGIN/END模式
BEGIN{}: 仅在开始处理文件中的文本之前执行一次
END{}:仅在文本处理完成之后执行一次
awk -F : 'BEGIN {print "USER USERID"} {print $1":"$3} END{print "end file"}' /etc/passwd //开头打印BEGIN结尾打印END
awk -F : '{print "USER USERID";print $1":"$3} END{print "end file"}' /etc/passwd //打印USER USERID再打印$1":"$3
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
seq 10 |awk 'i=0' 不打印
seq 10 |awk 'i=1' 打印1-10
seq 10 | awk 'i=!i' 打印奇数
seq 10 | awk '{i=!i;print i}' 1 0 1 0
seq 10 | awk '!(i=!i)' 打印偶数
seq 10 |awk -v i=1 'i=!i' 打印偶数
实例:BEGIN
常用的action分类
(1) Expressions:算术,比较表达式等
(2) Control statements:if, while等
(3) Compound statements:组合语句
(4) input statements
(5) output statements:print等
{ statements;... } 组合语句
if(condition) {statements;...}
if(condition) {statements;...} else {statements;...}
while(conditon) {statments;...}
do {statements;...} while(condition)
for(expr1;expr2;expr3) {statements;...}
break
continue
delete array[index]
delete array
exit
语法:if(condition){statement;...}[else statement]
if(condition1){statement1}else if(condition2){statement2}else{statement3}
使用场景:对awk取得的整行或某个字段做条件判断
示例:
awk -F: '{if($3>=1000)print $1,$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/{print $1}'|awk '$NF>=80{print $1,$5}'
df | awk '{if($0 ~ /\/dev\/sd/) print $1,$5}'
awk'BEGIN{ test=100;if(test>90){print "very good"}else if(test>60){ print "good"}else{print "no pass"}}'
语法:while(condition){statement;...}
条件“真”,进入循环;条件“假”,退出循环
使用场景:
对一行内的多个字段逐一类似处理时使用
对数组中的各元素逐一处理时使用
示例:
[root@centos7 ~]#awk -F: '{print $1,length($1)}' /etc/passwd
root 4
bin 3
[root@centos7 ~]#awk -F: '/^root/{i=1;while(i<NF){print $i,length($i);i++}}' /etc/passwd
root 4
x 1
0 1
0 1
root 4
/root 5
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
do-while循环
语法:do {statement;...}while(condition)
意义:无论真假,至少执行一次循环体
示例:
[root@centos7 ~]#awk 'BEGIN{ total=0;i=0;do{ total+=i;i++;}while(i<=100);print total}'
5050
[root@centos7 ~]#awk -F: 'BEGIN{sum=0;for(i=1;i<=100;i++)sum+=i;print sum}'
5050
语法:for(expr1;expr2;expr3) {statement;...}
常见用法:
for(variable assignment;condition;iterationprocess) {for-body}
特殊用法:能够遍历数组中的元素
语法:for(varin array) {for-body}
示例:awk '/^[[:space:]]*linux16/{for(i=1;i<=NF;i++) {print $i,length($i)}}' /etc/grub2.cfg
[root@centos7 ~]#time for((sum=0,i=1;i<=1000000;i++));do let sum+=i;done;echo $sum
real 0m5.898s
user 0m5.894s
sys 0m0.000s
500000500000
[root@centos7 ~]#time awk -F: 'BEGIN{sum=0;for(i=1;i<=1000000;i++)sum+=i;print sum}'
500000500000
real 0m0.100s
user 0m0.099s
sys 0m0.001s
[root@centos7 ~]#time seq -s+ 1000000 |bc
500000500000
real 0m0.381s
user 0m0.374s
sys 0m0.012s
[root@centos7 ~]#time awk 'BEGIN{i=1;sum=0;while(i<=1000000){sum+=i;i++};print sum}'
500000500000
real 0m0.085s
user 0m0.084s
sys 0m0.001s
awk 性能最好
语法:switch(expression) {case VALUE1 or /REGEXP/: statement1; case VALUE2 or /REGEXP2/: statement2; ...; default: statementn}
break和continue
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==66)break;sum+=i}print sum}' //1加到66
break [n]
continue [n]
next:提前结束对本行处理而直接进入下一行处理(awk自身循环)
awk -F: '{if($3%2!=0) next; print $1,$3}' /etc/passwd //偶数的uid
awk -F: '{if($3%2!=1) next; print $1,$3}' /etc/passwd //奇数的uid
关联数组:array[index-expression]
index-expression:
(1) 可使用任意字符串;字符串要使用双引号括起来
(2) 如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为“空串”
若要判断数组中是否存在某元素,要使用“index in array”格式进行遍历
示例:
weekdays["mon"]="Monday"
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";print weekdays["mon"]}'
awk '!arr[$0]++' dupfile
详细过程
awk '{!arr[$0]++;print $0, arr[$0]}' dupfile
[root@centos7 ~]#cat f1
aa
bb
cccc
ddd
aa
ddd
cccc
[root@centos7 ~]#awk 'arr[$0]++' f1 //重复行
aa
ddd
cccc
[root@centos7 ~]#awk '!arr[$0]++' f1 //不重复行(去重)
aa
bb
cccc
ddd
若要遍历数组中的每个元素,要使用for循环
for(var in array) {for-body}
注意:var会遍历array的每个索引
示例:
awk 'BEGIN{weekdays["mon"]="Monday";weekdays["tue"]="Tuesday";for(i in weekdays) {print weekdays[i]}}'
netstat -tan |awk '/^tcp/{ary[$NF]++}END{for(i in ary){print i,ary[i]}}'
awk '{ip[$1]++}END{for(i in ip) {print i,ip[i]}}' /var/log/httpd/access_log
ss -nt |awk -F "[ :]" '/ESTAB/{ip[$(NF-2)]++}END{for(i in ip){
print i,ip[i]}'
ss -nt |awk -F "[ :]+" '/ESTAB/{ip[$(NF-2)]++}END{for(i in ip){
print i,ip[i]}}'
ss -nt |awk -F "[ :]+" '/ESTAB/{print $(NF-2)}'|sort|uniq -c |sort -nr|head -n10
ss -nt |awk -F "[ :]+" '/ESTAB/{print $(NF-2)}'|sort|uniq -c |sort -nr|head -n10|while read count ip;do iptables -A INPUT -s $ip -j REJECT;done
数值处理:
rand():返回0和1之间一个随机数
awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'
字符串处理:
length([s]):返回指定字符串的长度
sub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并将第一个匹配的内容替换为s
echo "2008:08:08 08:08:08" | awk 'sub(/:/,"-",$1)'
2008-08:08 08:08:08
gsub(r,s,[t]):对t字符串进行搜索r表示的模式匹配的内容,并全部替换为s所表示的内容
echo "2008:08:08 08:08:08" | awk 'gsub(/:/,“-",$0)'
2008-08-08 08-08-08
split(s,array,[r]):以r为分隔符,切割字符串s,并将切割后的结果保存至array所表示的数组中,第一个索引值为1,第二个索引值为2,...
netstat -tn | awk '/^tcp\>/{split($5,ip,":");count[ip[1]]++}END{for (i in count) {print i,count[i]}}' 外部连接ip
实例
[root@centos7]#awk 'BEGIN{v="我" ;print length(v)}'
1
[root@centos7]#awk 'BEGIN{srand();print rand()}' //随机数
0.704931
[root@centos7 wang]#awk 'BEGIN{srand();print int(rand()*100)}' //取整数
52
awk 'BEGIN{srand(); for (i=1;i<=10;i++)print int(rand()*100) }'//生成10个随机整数
[root@centos7]# echo "11:22:33 44:55:66" | awk '{split($0,str,":")}END{for(i in str){print i,str[i]}}'
4 55
5 66
1 11
2 22
3 33 44
统计文件中单词的个数
awk '{for(i=1;i<=NF;i++)word[$i]++}END{for(i in word)print word[i],i}' /etc/profile|sort -nr
[root@centos7 ~]#cat f1
aa 100 male
bb 20 male
cc 50 female
dd 60 female
ee 99 xxx
rr 150 ***
[root@centos7 ~]#awk '{if($3=="male"){mnum++;msum+=$2}else{fnum++;fsum+=$2}}END{printf "male:%d %.2f\nfemale:%d %.2f",mnum,msum/mnum,fnum,fsum/fnum}' f1 //写死了
male:2 60.00
female:4 89.75
[root@centos7 ~]#awk '{num[$3]++;sum[$3]+=$2}END{for(sex in num){print sex,sum[sex],sum[sex]/num[sex]}}' f1 //灵活
female 110 55
male 120 60
*** 150 150
xxx 99 99
格式:
function name ( parameter, parameter, ... ) {
statements
return expression
}
示例:
(1)
[root@centos7 ~]cat f1.txt
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{a=3;b=2;print max(a,b)}
[root@centos7 ~]#awk -f f1
3
(2)
[root@centos7 ~]cat f1.txt
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{print max(a,b)}
[root@centos7 ~]#awk -v a=3 -v b=2 -f f1.txt
3
(3)
[root@centos7 ~]cat f1.awk
#! /bin/awk -f
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{print max(a,b)}
[root@centos7 ~]#./f1.awk -v a=3 -v b=2 -f
3
system命令
空格是awk中的字符串连接符,如果system中需要使用awk中的变量可以使用空格分隔,或者说除了awk的变量外其他一律用""引用起来。
[root@centos7 ~]#awk 'BEGIN{score=100; system("echo your score is " score) }' //打印变量 前面加空格 还有就是写到外面
your score is 100
[root@centos7 ~]#awk BEGIN'{system("hostname") }'
centos7.qifei.com
[root@centos7 ~]#ss -nt |awk -F "[ :]+" '/^ESTAB/{IP[$(NF-2)]++}END{for(i in IP){if(IP[i] >3)system("iptables -A INPUT -s "i" -j REJECT")}}' //连接数大于3加入防火墙
iptables -vnL //查看禁用
将awk程序写成脚本,直接调用或执行
示例:
[root@centos7 ~]#cat f1.awk
{if($3>=1000)print $1,$3}
[root@centos7 ~]#awk -F: -f f1.awk /etc/passwd
-----------------------
[root@centos7 ~]#cat f2.awk
#!/bin/awk –f
#this is a awkscript
{if($3>=1000)print $1,$3}
[root@centos7 ~]#chmod +x f2.awk
[root@centos7 ~]#f2.awk –F: /etc/passwd
格式:
awkfile var=value var2=value2... Inputfile
注意:在BEGIN过程中不可用。直到首行输入完成以后,变量才可用。可以通过-v参数,让awk在执行BEGIN之前得到变量的值。命令行中每一个指定的变量都需要一个-v参数
示例:
[root@centos7 ~]#cat test.awk
#!/bin/awk –f
{if($3 >=min && $3<=max)print $1,$3}
[root@centos7 ~]#chmod +x test.awk
[root@centos7 ~]#test.awk -F: min=100 max=200 /etc/passwd
---------------------
[root@centos7 ~]cat f1.awk
#! /bin/awk -f
function max(v1,v2) {
v1>v2?var=v1:var=v2
return var
}
BEGIN{print max(a,b)}
[root@centos7 ~]#./f1.awk -v a=3 -v b=2 -f
3
[root@centos7 ~]#ss -nt |awk -F "[ :]+" '/^ESTAB/{IP[$(NF-2)]++}END{for(i in IP){if(IP[i] >3)system("iptables -A INPUT -s "i" -j REJECT")}}' //连接数大于3加入防火墙
iptables -vnL //查看禁用
POST --> Boot Sequence --> Bootloader --> kernel + initramfs(initrd) --> rootfs--> /sbin/init
init:
CentOS 5: SysVinit
CentOS 6: Upstart
CentOS 7: Systemd
Systemd:系统启动和服务器守护进程管理器,负责在系统启动或运行时,激活系统资源,服务器进程和其它进程
Systemd新特性:
系统引导时实现服务并行启动
按需启动守护进程(需要那个启动那个)
自动化的服务依赖关系管理(如果a依赖b会自动加载;与centos6相反)
同时采用socket式与D-Bus(桌面)总线式激活服务(ip地址加端口号 ss -ntl)
系统状态快照
核心概念:unit
unit表示不同类型的systemd对象,通过配置文件进行标识和配置;文件中主要包含了系统服务、监听socket、保存的系统快照以及其它与init相关的信息
配置文件:
/usr/lib/systemd/system:每个服务最主要的启动脚本设置,类似于之前的/etc/init.d/(大概与centos6 /etc/init.d/)
/run/systemd/system:系统执行过程中所产生的服务脚本,比上面目录优先运行
/etc/systemd/system:管理员建立的执行脚本,类似于/etc/rc.d/rcN.d/Sxx类的功能,比上面目录优先运行
systemctl status httpd.service
Systemctl –t help 查看unit类型
**Service unit: 文件扩展名为.service, 用于定义系统服务
**Target unit: 文件扩展名为.target,用于模拟实现运行级别(简单定义下 runlevel)
Device unit: .device, 用于定义内核识别的设备
Mount unit: .mount, 定义文件系统挂载点
**Socket unit: .socket,用于标识进程间通信用的socket文件,也可在系统启动时,延迟启动服务,实现按需启动
Snapshot unit: .snapshot, 管理系统快照
Swap unit: .swap, 用于标识swap设备
Automount unit: .automount,文件系统的自动挂载点(ls /misc/cd)
Path unit: .path,用于定义文件系统中的一个文件或目录使用,常用于当文件系统变化时,延迟激活服务,如:spool 目录
没有**一般不修改
[root@centos7 system]#systemctl get-default //图形的默认级别
graphical.target