awk -F":" '{print $1}' /etc/passwd
cat /etc/passwd | awk -F":" '{print $1}'
$0 代表整行
$NF 代表最后一列
NF 当前awk正在处理的行的字段数
NR 当前awk正在处理的第几行
awk -F: 'BEGIN{ ...处理整个文件前执行的代码... }{ ...处理过程中执行的代码.. }END{...处理完整个文件之后执行的代码...}'
awk 流操作命令
打印所有的行 awk '{print $0}' /etc/passwd 或 awk -F":" '{print $1}'
打印第一列 awk -F: '{print $1}' /etc/passwd
打印1,3列 awk -F: '{print $1,$3}' /etc/passwd
打印每行的最后一列 awk -F: '{print $NF}' /etc/passwd
打印每行的字段数 awk -F: '{print NF}' /etc/passwd
打印页眉和页尾:
awk 'BEGIN{print "=================These are passwd contents============="} {print $0} END{ print "===============End of Contents==============="}' /etc/passwd
打印所有字段的总数:awk -F: 'BEGIN{ c=0 } { c=c+NF } END{ print c }' /etc/passwd
if ( condition ) { command } else { command }
打印第八行: awk '{ if ( NR==8 ) { print $0 } }' /etc/passwd
关系操作符号:
== 等于 <----#####
!= 不等于
>=
<=
>
<
打印字段数目大于4的行 awk -F: '{ if ( NF>4 ) {print} }' /tmp/test/passwd
awk -F: ' NF>4 { print } ' /tmp/test/passwd
打印字段数目大于4的行的总数 awk -F: 'BEGIN{ c=0 } { if (NF>4) { c++ } } END{print c}' /tmp/test/passwd
逻辑操作符:
&& 逻辑与
|| 逻辑或
! 逻辑非,取反
打印第5到10行 awk ' NR>=5 && NR<=10 {print}' /etc/passwd
打印uid在30~50范围内的用户名 awk -F: '$3>30 && $3<50 {print $1}' /etc/passwd
隔行打印(隔行删除) awk 'NR%2==0 {print }' /etc/passwd
运算操作符号
+
-
*
/
%
^ <-- 2^3 2的3次方
++ <-- 自加1
--
利用awk进行算术运算
echo | awk '{print 1.7/3^4}'
# awk -f 01.awk /etc/passwd
[root@dns shell_04]# cat 01.awk
BEGIN{
FS=":"
}
{
print $1
}
改写成外部脚本调用的形式:
# awk -f 01.awk /etc/passwd
[root@dns shell_04]# cat 01.awk
BEGIN{
FS=":"
}
{
print $1
}
01.sh
awk -F: 'BEGIN{ c=0 } { if (NF>4) { c++ } } END{print c}' /tmp/test/passwd
BEGIN{
FS=":"
c=0
}
{
if (NF>4)
{
c++
}
}
END{
print c
}
执行: awk -f 201004091/01.sh /etc/passwd
while (condition) statement
do statement while (condition)
for (expr1; expr2; expr3) statement
for (var in array) statement
shell的写法:
while [ condition]
do
command
done
awk 的写法:
while (condition)
{
command
}
shell的写法:
until [ condition ]
do
.....
done
awk的写法:
do
{
....
} while (condition) <---不管开始的时候条件是否成立,都执行一次循环体里的代码
shell的写法:
for ((expr1; expr2; expr3))
do
.....
done
for var in array
do
....
done
awk的写法:
for (expr1; expr2; expr3)
{
command
}
for (var in array)
{
command
}
倒序排列所有字段
root:x:0:0:tanpao,uplooking,124324324,24235454:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
---》
/bin/bash:/root...:root
for (expr1; expr2; expr3)
{
command
}
思路: 利用一个循环变量i 记录每行字段的总数(7),然后每次循环都答应一个字段
$i --> i--
print $i
for (i=NF;i>0;i--)
{
}
BEGIN{
FS=":"
}
{
for (i=NF;i>0;i--)
{
if ( i!=1 )
{
printf("%s%s",$i,FS)
- }
else
{
#printf("%s%s",$i,"\n")
printf("%s\n",$i)
}
}
#printf("\n")
}
一行代码模式:
[root@qianxin df]# awk -F: '{for(a=NF;a>0;a--){if(a!=1){printf ("%s%s",$a,FS)}else{printf ("%s\n",$a)}}}' /tmp/passwd
%d------------------------数值
%s------------------------字符串
字符串的匹配
$0------------------------整行
== -----------------------绝对匹配
$1=="root"
~ ------------------------相对匹配
$1~/root/
!=------------------------不绝对匹配
!~------------------------不相对匹配
输出第一列完全等于root的行
awk -F: '$1=="root"{print $0}' /etc/passwd
相反:
awk -F: '$1!="root" {print $0}' /etc/passwd
输出第一列包含root关键字的行
awk -F: '$1 ~ /root/ {print $0}' /tmp/test/passwd
相反:
awk -F: '$1 !~ /root/ {print $0}' /tmp/test/passwd
awk -F: '! /root/ {print $0}' /tmp/test/passwd <--区别:整行都不包行root
把系统上所有不允许登录的帐号都打印出来,并且最后统计一个数字
/sbin/nologin
/bin/false
单行命令:
#awk -F: 'BEGIN{c=0}$NF~"/sbin/nologin" || $NF~"/bin/false"{printf ("%s\t",$1)}{c++}END{printf "\n%s\n",c}' /tmp/passwd
if , == ,~ ,外部脚本,printf
输出格式:
roy tom mary
total:3
BEGIN{
FS=":"
a=0
b=0
}
{
if ( $7 == "/sbin/nologin" )
{
printf ("%s\t",$1)
a++
}
if ($7 == "/bin/false" )
{
printf ("%s\t",$1)
b++
}
c=a+b
}
END{
# c=$a+$b
printf ("\ntotal:%d\n",c)
}
~
只用一行来表示:awk -F: 'BEGIN{a=0}{if($NF~"\/sbin\/nologin" || $NF~"\/bin\/false"){printf ("%s\t",$1);c++}}END{print c}' /etc/passwd
输出格式:
roy tom mary
total:3
BEGIN{
c=0
FS=":"
}
{
if ($NF~/\/sbin\/nologin/ || $NF~/\/bin\/false/)
{
printf("%s\t",$1)
c++
}
}
END{
printf("\ntotal:%d\n",c)
}
一行命令的形式
awk 'BEGIN{c=0;FS=":"}{ if ($NF~/\/sbin\/nologin/ || $NF~/\/bin\/false/) { printf("%s\t",$1);c++ } }END{printf("\ntotal:%d\n",c)}'
字符串函数
length([s])
BEGIN{
str="welcome to upl"
}
{
#print length("welcome to upl")
print length(str)
}
index(s, t)
BEGIN{
str="welcome to upl"
}
{
#print length("welcome to upl")
print length(str)
print index(str,"c") 《---返回4,如果找不到,就返回0,如果有多个匹配,就找出第一个匹配
}
改变大小写:
BEGIN{
str="Welcome to upl"
}
{
#print length("welcome to upl")
print length(str)
print index(str,"l")
print tolower(str)
print toupper(str)
}
例子:把下列的姓名列表中的姓打印出来
提示: 首先找到“,”所在的位置,然后通过子串截取函数,把姓打印出来
Michle,Jackson
Tom,Green
San,Zhang
# cat /tmp/test/name.txt | awk '{pos=index($0,",");print substr($0,pos+1)}'
Jackson
Green
Zhang
例子:要求把用户描述的前15个字符打印出来
San Zhang,He is man,live in shenzhen.
Si Li,He is a gay boy....Do you like him?
Li Xiao,She is a beauty! Everyone likes her!
# cat /tmp/test/name.txt | awk '{pos=index($0,",");print substr($0,pos+1,15)}'
He is man,live
He is a gay boy
She is a beauty
或者
# cat /tmp/test/name.txt | awk '{print substr($0,index($0,",")+1,15)}'
字符串替换
sub
gsub
BEGIN{
str="Welcome to upl"
}
{
#print length("welcome to upl")
print length(str)
print index(str,"l")
print tolower(str)
print toupper(str)
sub("o","-",str) # 把str中第一个找到的“o”替换成“-”
print str
gsub("l","@",str) #把所有匹配都替换
print str
}
例子:利用awk 找到某个目录下的最大尺寸文件和最小尺寸文件,最后输出所有文件的平均尺寸
Large Size: Max_file.txt
Low Size: Min_file.txt
Avarge Size: 55K
BEGIN{
total=0
}
{
total += $5
if ( NR==1 ){
print "Max Size:"$5
}
}
END{
print "Mini Size:"$5
print "Average Size:"total/NR
}
传输外部变量进入awk脚本
#awk -v nvar="$a" -f 10.awk
传递shell变量到awk脚本中
方法一:
# echo | awk -v nvar="$a" -f 10.awk
BEGIN{
print nvar
}
# echo | awk -v nvar="$a" '{print nvar}'
方法二:
[root@dns shell_04]# export bbb=119
[root@dns shell_04]# echo | awk 'BEGIN{print ENVIRON["bbb"]}'
119
方式三:
[root@dns shell_04]# c=007
[root@dns shell_04]# echo | awk 'BEGIN{print "'$c'"}'
007
========================================================================
Tcpwrapper
#ldd /usr/sbin/vsftp | grep wrap
libwrap.so.0<--------------------如果返回值中有调用这种库,则明确支持Tcpwrapper
配置文件/etc/hosts.allow
/etc/hosts.deny
规则判断的原理:首先去读取hosts.allow文件,如果找到匹配的规则,就停止继续往下匹配,更不去匹配hosts.deny,如果hosts.allow找不到匹配的规则,就读取hosts.deny
# cat /etc/hosts.allow
sshd:10.1.1.0/255.255.255.0 EXCEPT 10.1.1.56
等价于: 允许10.1.1.1~10.1.1.55 , 10.1.1.57~10.1.1.254的客户IP去访问
# cat /etc/hosts.deny
sshd : 10.1.1.56
以上规则结合起来的作用:仅仅拒绝了10.1.1.56访问sshd
例子:
想只允许10.1.1.0/24网段的客户去访问sshd
# vim hosts.allow
sshd:10.1.1.0/255.255.255.0
# vim hosts.deny
sshd:ALL
或者 只修改一个文件
# vim hosts.allow
# vim hosts.deny
sshd:ALL EXCEPT 10.1.1.0/255.255.255.0
例子: 允许所有人访问,但不允许10.1.1.0/24访问,除了10.1.1.56可以访问之外。
# vim hosts.allow
sshd:ALL EXCEPT 10.1.1.0/255.255.255.0 EXCEPT 10.1.1.56
# vim hosts.deny
sshd:ALL
练习:
把连续三次企图通过ssh远程登录服务器的恶意IP都添加到tcpwrapper相关的配置文件,把恶意IP拒绝掉。
规则文件不允许有重复的IP
#lastb -ai | grep ssh | awk '{print $NF}' | uniq -c | awk '$1>=3{print $NF}'
#!/bin/bash
newip=$(lastb -ai | grep ssh | awk '{print $NF}' | uniq -c | awk '$1>=3{print $2}')
oldip=$(cat /etc/hosts.deny | grep sshd | awk -F: '{print $2}')
oldtmp=$(mktemp)
echo $oldip > $oldtmp
for a in $newip
do
grep "$a" $oldtmp > /dev/null
if [ "$?" -eq 1 ];then
echo $(cat $oldtmp) $a > $oldtmp
fi
done
cat /etc/hosts.deny | grep -v "sshd" > /etc/hosts.deny
echo "sshd: $(cat $oldtmp)" >> /etc/hosts.deny
rm -f $oldtmp