Bootstrap

Shell高级练习脚本15个

目录

1.sed的基本使用

2.sed的高级使用

3.awk的基本使用

4.awk高级用法

其他


1.sed的基本使用

#!/bin/bash
sed 'p' /etc/hosts  # 使用sed所有行数,但是sed会默认把读取到的数据打印到页面,所以会先打印一次,再把会再打印一次
sed -n 'p' /etc/hosts         # 只打印一次所有行数
sed -n '1p' /etc/hosts        # 只打第一行
df -h | sed -n '2p'           # 支持管道打印
sed -n '1,3p' /mnt/passwd     # 显示1到3行
sed -n '1p;3p;5p' /mnt/passwd # 打印1,3,5行
sed -n '4,$p' /mnt/passwd     # 显示第4行到末尾所有行数
sed -n '3,+3p' /mnt/passwd    # 显示第3行后再加3行
sed -n '1~2p' /mnt/passwd     # 显示奇数行(步长为2)及1,3,5,7....
sed -n '1~4p' /mnt/passwd     # 显示奇数行(步长为4)及1,5,9,13...
sed -n '3~4p' /mnt/passwd     # 显示3,7,11.....
sed -n '2~2p' /mnt/passwd     # 显示偶数行(步长为2)及2,4,6.....
sed -n '4~2p' /mnt/passwd     # 显示偶数行(步长为2)及4,6,8....
sed -n '$p' /mnt/passwd       # 显示文件最后一行并显示
sed -n '/root/p' /mnt/passwd  # 显示包含root的行并显示
sed -n 'bash$/p' /mnt/passwd  # 显示以bash结尾的行
sed -n '/s...:x/p' /mnt/passwd  # 显示字母以s开头,以:x结尾,中间包含任意三个字符的数据
sed -n '[0-9]' /mnt/passwd      # 匹配包含数字的行
sed -n '/^http/p' /etc/services # 显示以http开头的行 
sed -nr '/^(icmp|igmp)/p' /etc/protocols # 开启扩展正则,默认不支持
sed -n '\cUIDcp' /etc/login.defs  # 正则匹配包含UID的行
sed -n '\xbashxp' /ect/shells   # 正则包含bash的行并显示出来
sed -n '\1bash1p' /ect/shells   # 正则包含bash的行并显示出来
sed -n '\:bash:p' /ect/shells   # 正则包含bash的行并显示出来
sed -n '1' /etc/shell           # 显示数据内容时打印控制字符
sed -n '/root/=' /mnt/passwd    # 显示包含root字符串的行号
sed -n '3=' /mnt/passwd         # 显示第三行的行号
sed -n '$=' /mnt/passwd         # 显示最后一行的行号
sed -n '1!p' /etc/hosts         # 显示除第一行外的所有行数据
sed -n '/bash/!p' /mnt/passwd   # 显示除bash外的所有行数据
sed '1a add test line' /mnt/passwd # 在第一行后添加一行数据,在屏幕上显示有添加成功,但是源数据不会变
sed -i '1a add test line' /mnt/passwd # 在第一行后添加一行数据,修改源文件,并不备份
sed -i.bak '2d' /mnt/passwd     # 备份后在修改源文件
sed '1i add test line' /mnt/passwd # 在第一行前添加一行数据,修改源文件,并不备份'
sed '/new/a temp line' /mnt/passwd # 显示包含new的行后添加temp line
sed '/new/a temp line;3p;2i add lie' /mnt/passwd # 显示包含new的行后添加temp line3p;2i add lie,使用i和a后面的参数将不生效
sed 'd' /mnt/passwd             # 删除全文
sed '1d' /mnt/passwd            # 删除第一行数据
sed -i '/^$/d' /mnt/passwd      # 删除空白行
sed -i '/^#/d' /mnt/passwd      # 删除以#开头的行
sed '/local/d' /mnt/passwd      # 删除以包含local的行
sed '2c modify line' /mnt/passwd # 将第2行替换成新的内容
sed 'c modify line' /mnt/passwd # 将所有行替换成新的内容
sed '/new/c line' /mnt/passwd   # 将包含new的行替换成line
sed 'r /etc/hosts /mnt/passwd'  # 读取/etc/hosts所有文件内容到/mnt/passwd内
sed 'w /etc/hosts /mnt/passwd'  # 读取/etc/hosts所有文件内容到/mnt/passwd文件(如果文件存在则覆盖)
sed '1r /etc/hosts /mnt/passwd' # 读取/etc/hosts第一行文件内容到/mnt/passwd内
sed '3r /etc/hosts /mnt/passwd' # 读取/etc/hosts第三行文件内容到/mnt/passwd内
sed '1,3w /etc/hosts /mnt/passwd'  # 仅读取/etc/hosts1~3行文件内容到/mnt/passwd文件(如果文件存在则覆盖)
sed '3q' /mnt/passwd            # 读取文件第三行时并退出sed
sed '1s/test1/hi' /mnt/passwd   # 仅对第1行执行替换操作
sed 's/o/O' /mnt/passwd         # 仅替换每行的第一个o
sed 's/o/O/g' /mnt/passwd       # 仅替换所有的o
sed 's/o/O/2' /mnt/passwd       # 仅替换每行的第二个字母o
sed 's/o/O/2p' /mnt/passwd      # 仅替换每行的第二个字母o并显示出来
sed 's/test/o/i'                # 仅替换每行的第一个o,忽略大小写
echo '/etc/hosts' | sed 's/^/ls -l /e'  # 将/etc/hosts替换ls -l /etc/hosts表示将替换后的内容当成shell命令执行一次
echo '/etc/hosts' | sed 's#^#ls -l #e' # 与上类似,只是把\换成了#
sed 's/the//' /mnt/passwd       # 将the替换成空即删除
echo '"hello" "world"' | sed 's/\".*\"//' # 将前面的输出替换成空
echo '"hello" "world"' | sed 's/\"[^\"]*\"//' # 将前面的以"号开头中间任意数据到"结尾,替换成空,也就是只打印world
sed -r 's/^(.)(.*)(.)$/\3\2\1/' /mnt/passwd # 使用()保留功能将每行首位对调
sed 's/\/sbin\/nologin/\/bin\/sh/' /mnt/passwd     # 使用转译符把/sbin/nologin替换为/bin/sh/
sed 's/#sbin#nologin/#bin#sh/' /mnt/passwd # 与上一致,不过把转译符换成了#
sed 'sx/sbin/nologinx/bin/shx' /mnt/passwd # 与上一致,把转译符换成了x
sed -n -e '1p'  -e '3p' /mnt/passwd        # 使用多命令模式打印第1行和第3行
sed '/world/s/hello/hi;s/the//' test.txt   # 不使用分组只有第一条生效,只匹配第一行,而第二个命令会匹配所有
sed '/world/{s/hello/hi;s/the//}' test.txt # 使用分组只有第一条生效
​
​
###---------使用文件的方式进行sed--------###
~]# vim script.s #后缀任意
1c ceshi test   # 将第一行替换为ceshi test
2{
   p            # 先匹配第二行打印改行的所有数据
   s/g/G/       # 再将第一个小写g提换成大写
}
/[0-9]/d        # 匹配包含数字的行删除
/root/{
   s/h/H/       # 匹配包含root的行把小写h替换成大写的H
   s/root/zheshiceshi/  # 然后将root替换成zheshiceshi
}
# 执行
~]# sed -f script.s /mnt/passwd

2.sed的高级使用

#!/bin/bash
sed '2h;5g' ceshi2.sh    # 将第二行的数据覆盖第5行,效果是先打印第2行保存到保留空间,将保留空间的回车符覆盖,在打印第5行,把保留空间的数据覆盖掉模式空间的数据
sed '2h;5G' ceshi2.sh    # 把保留空间的数据追加到第5行后
sed '2H;5G' ceshi2.sh    # 把数据追加到保留空间,此时保留空间有一行数据可一个回车符,再追加到第5行后
sed 'n;d' ceshi2.sh      # 删除偶数行,效果是(sed是逐行处理的,sed先把数据存入保存空间,先读取一行再删除一行,依次类推,就是删除偶数行)
sed -n '2{N;1}' ceshi2.sh   # 先读取第2行数据到模式空间,再使用N读取下一行追加到模式空间种,此时模式空间就有2行数据了,在使用1打印所有字符,(p不打印特殊字符)
sed 'N;s/\n//' ceshi.txt    # 没两行合并为一行
sed 'y/hg/HG/' ceshi2.txt   # 将小写的h和g替换成大写的H和G,y:以字符为单位替换
sed 'y/hg/12' ceshi2.txt
sed -n ':top;=;p;4b top' ceshi2.txt | head -14  # 执行结果为第一行第一名称top的标签,执行=和p指令,屏幕输出1和第一行的数据此时第一行不等于第4行所以不会执行,第二行类似,一直到第4行,因为指定了第四行等于top又会跳到执行=和p指令,但是指令仅仅执行这个又会会到第4行,一直反复成了死循环
sed -n '=;p' ceshi2.txt    # 显示行号和内容
sed -n '/go/b label;=;:label;p' ceshi2.txt      # 执行结果只是不打印匹配go行的行号;第一行如果没有则正常执行=和p及内容,直至匹配到有go的行直接跳过=指令;不多打印行号
sed 's/\./!/' ceshi2.txt   # 把匹配到的所有行的第一个点替换成!号
sed '/bejing/b end;s/\./!/;:end' ceshi2.txt  # 当匹配到bejing字符的行的时候就会替换并通过b 指令跳到末尾,其他的正常执行
sed '/s/hello/nihao' ceshi2.txt  # 把匹配到的所有行的第一个hello>替换成niha
sed '/hello/{s/hello/nihao;:next;n;b next}' cheshi2.txt # 把匹配到的所有行的第一个hello替换成niha,sed并把数据读取到模式空间,当匹配就替换,如果最后没有b next指令则结束
echo -e "phone:\n\t12345678901" > text.txt
sed -r 'N;s/\n//;s/: +/: /' text.txt                  # 把两行合并成一行
echo -e "phone:\n\t12345678901\nphone:   98765432109\nphone:\n\t1112223334445556" > text.txt
sed -r '"start;/:$/N;s/\n +//;t start' text.txt       # 把两行合并成一行,定义start标签,执行条件:结尾的行N读取下一条数据到模式空间,最后s把\n和其他字符替换成空替换,最后只有当之前的条件符合才会执行t的标签start
echo fe:54:00:8f:25:92 | sed 's/://g'                 # 删除分隔符
echo fe54008f2592 | sed -r 's/([^:]*)([0-9a-f]{2})/\1:\2/'   # 只有最后一个25:有:号
echo fe54008f2592 | sed -r ':loop;s/([^:]*)([0-9a-f]{2})/\1:\2/;t loop' # 使用分号循环则会打印fe:54:00:8f:25:92

3.awk的基本使用

#!/bin/bash
free | awk '{print $2}'                 # 逐行打印第2行
free | awk '{print NR}'                 # 输出行号
free | awk '{print NF}'                 # 输出每行数据的列数
awk '{print $2}' /etc/passwd            # 打印文件每行第2列
awk '{print $3}' /etc/passwd            # 打印文件每行第3列
awk '{print $0}' /etc/passwd            # 打印每行全部内容
awk '{print}' /etc/passwd               # 打印每行全部内容
awk '{print NR}' /etc/passwd            # 打印当前行行号
awk '{print NR}' /etc/passwd /etc/hosts 
awk '{print NF}' /etc/passwd            # 打印每行数据的列数
awk '{print $NF}' /etc/passwd           # 打印每行的最后1列
awk '{print $(NF-1)}' /etc/passwd       # 打印每行的倒数第2列
awk '{print $(NF-2)}' /etc/passwd       # 打印每行的倒数第3列
awk '{print FILENAME}' /etc/passwd      # 打印文件名(有多少行打印多少个文件名)
awk -v x="kali" '{print x}' /etc/passwd # -v定义变量输出变量(有多少行打印多少个变量)
awk -v x="kali" -v y="yao" '{print x,y}' /etc/passwd
awk -v x="kali" -v y="yao" '{print y,x}' /etc/passwd  # 变量循序调换
x="hello"                               # 自定义系统变量“
awk -v i=$x '{print i}' /etc/passwd     # 组合变量(有多少行打印多少个变量)
i="hello"                               # 自定义系统变量
awk '{print "'$i'"}' /etc/passwd        # awk调用系统变量
awk -v FS=":" '{print $1}' /etc/passwd  # 重新定义分隔符
awk -v FS="[:,/]" '{print $11}' /etc/passwd # 使用:冒号,逗号或者横线-为分隔符
awk -v FS="[:,-]" '{print $11}' /etc/passwd
awk -F: '{print $1}' /etc/passwd        # 定义冒号为分隔符
awk -F"[:,-]" /etc/passwd               # 使用集合定义分隔符
cat > test.txt << EOF
hello the world!
other men live to eat, while I eat to live
It is never too late to mend
EOF
awk -v RS="," '{print $1}' test/hi.txt  # 定义已逗号为分隔行的符打印第一列(默认以\n)
awk '{print $1,$2,$3}' test/hi.txt      # 默认已\n为分隔符打印
awk -v OFS=":" '{print $1,$2,$3}' test/hi.txt  # 定义分段分隔符为:冒号(默认空格)
awk -v OFS="-" '{print $1,$2,$3}' test/hi.txt
awk -v OFS="\t" '{print $1,$2,$3}' test/hi.txt
awk -v OFS=". " '{print NR,$0}' test/hi.txt  # 定义两个数据直间的分隔符为点和空格(两个数据分别时打印行号和所有数据)
awk '{print}' test/hi.txt              # 默认打印,行号分隔符\n,列号分隔符空格
awk -v ORS=":" '{print}' test/hi.txt   # 自定义行号分隔符,打印所有
awk '{print "CPU"}' test/hi.txt        # 使用print输出常量,(有多少行打印多少个)
awk '{print "data:",$1}' test/hi.txt   
awk '{print 123456}' test/hi.txt       # 使用print输出数字(有多少行打印多少个)
awk '{print "第一列:"$1,"\t第二列:"$2}' test/hi.txt
awk '/world/{print}' test/hi.txt       # 打印包含world的行
awk '/world/' test/hi.txt              # 与上类似
awk '$2~/the/' test/hi.txt             # 每行第2列正则匹配the
awk '$3~/never/{print $1,$4,$5}' test/hi.txt # 逐行匹配never关键字,包含则打印第1,4,5列
awk '$4~/to/' test/hi.txt              # 第四列包含to的行
awk '$4=="to"' test/hi.txt             # 第四列精确匹配to
awk '$2!="the"' test/hi.txt            # 第2列不等于the
awk -F: '$3<=10' /etc/passwd           # 匹配第3列小于10的行
awk -F: '$3<=10{print $1}' /etc/passwd # 匹配第3列小于10的行的第一列
awk 'NR==4' /etc/passwd                # 仅显示第四行数据
awk -F: '$3>1&&$3<5' /etc/passwd       # 逻辑与,满足两个条件
awk -F: '$3==1||$3==5' /etc/passwd     # 逻辑或,满足两个条件之一
awk 'BEGIN{print "OK"}'                # 在读取数据之前执行
awk 'BEGIN{print "OK"}' /etc/passwd    # 与上类似
awk 'END{print NR}' /etc/passwd        # NR变量的值在读取第一行的时候时1,第二行是2,直至最后,END最后打印NR的值也就是最后的值
awk -F: 'BEGIN{print "用户名 UID 解析器"} {print $1,$3,$7} END{print "总计有"NR"个账户"}' /etc/passwd
awk -F: 'BEGIN{print "用户名 UID 解析器"} {print $1,$3,$7} END{print "总计有"NR"个账户"}' /etc/passwd | column -t
awk 'BEGIN{print 2+3}'                 # 加法运算
awk 'BEGIN{print 10-3}'                # 减法运算
awk 'BEGIN{print 2*3}'                 # 乘法运算
awk 'BEGIN{print 2/3}'                 # 除法运算
awk 'BEGIN{print 6%3}'                 # 取余运算
awk 'BEGIN{print 2**3}'                # 幂运算
awk 'BEGIN{x=8;y=2;print x-y}'         # 对变量进行减法
awk 'BEGIN{x=8;y=2;print x*y}'         # 对变量进行乘法
awk 'BEGIN{x=1;x++;print x}'           # x=x+1
awk 'BEGIN{x=1;x--;print x}'           # x=x-1
awk 'BEGIN{x=1;x+=8;print x}'          # x=x+8
awk 'BEGIN{x=1;x-=2;print x}'          # x=x-2
awk 'BEGIN{x=1;x*=2;print x}'          # x=x*2
awk 'BEGIN{x=1;x/=2;print x}'          # x=x/2
awk 'BEGIN{x=1;x%=2;print x}'          # x=x%2
awk 'BEGIN{print x+8}'                 # print 0+8默认未定义的变量为0
awk 'BEGIN{print x*8}'                 # print 0*8
awk 'BEGIN{print "["x"]","["y"]"'      # x和y变量默认为空
awk '/bash$/{x++} END{print x}' /etc/passwd # 匹配包含bash的行x变量加1
who | awk '$1=="root"{x++} END{print x}'    # 统计root登录次数
seq 200 | awk '$1%7==0 && $1~/7/'           # 循环200,过滤第一行除余7等于0并且包含7
df | tail -n +2 | awk '{sum+=$4} END{print sum}' # 从第2行开始显示,sum原始值默认0,$4第四列为容量前面的命令输出管道给awk读取一行就执行一次sum+11111.....,最后输出 # 与上类似,$5为容量
ls -l /etc/*.conf | awk '{sum+=$5} END{print sum}' # 与上类似,$5为容量
ls -l /etc/ | awk '/^-/{sum+=$5} END{print "文件总和:"sum"."}' # 普通文件总和

4.awk高级用法

###---------------if语句的使用------------###
#!/bin/bash
ps -eo user,pid,pcpu,comm          # 普通查看进程列表(-e所有进程,-o指定进程)
ps -eo user,pid,pcpu,comm | awk '{if ($3>0.5){print}}' # 查看第三列cpu大于0.5的行
ps -eo user,pid,rss,comm | awk '{if ($3>1024){print}}' # 查看第三列进程占用内存大于1024>的行
awk -F: '{if ($3<1000){x++}else{y++}}END{print "系统用户个数:"x,"普通用户个数:"y}' /etc/passwd                            # 双重if,awk这里用的是else
# if配合END
ls -l /etc/ | awk \
'{
if ($1~/^-/) {x++} else {y++} \
}                              \END {print ".通文件个数:"x,"目录个数:"y}'
                         
                         
seq 10 | awk \           
'{    \
if ($1%2==0) {print $1"是偶数";x++}else{print $1"是奇数";y++} \
}
END{print "偶数个数:"x,"奇数个数:"y}'
# 多分支if
awk 'if($2>=90){print $1,\t"完美"} else if($2>=80) {print $1,\t"优秀" else if($2>=70) {print $1,\t"良好"} else if($2>=60) {print $1,\t"勉强"} else {print $1,"\t差强人意"}' test.txt
​
​
###------------数组和for循环--------------###
#!/bin/bash
awk 'BEGIN{a[0]=11;print a[0]}'         # 定义数组和调用数组
awk 'BEGIN{a[0]=11;a[1]=22;print a[0],a[1]}'
awk 'BEGIN{tom["age"]=22;tom["addr"]="beijing";print tom["age"],tom["addr"]}'
awk 'BEGIN{tom["age"]=22;tom["addr"]="beijing";print tom["addr"],tom["age"]}'
awk 'BEGIN{a[0][0]=11;a[0][1]=22;print a[0][1],a[0][0]}'    # 创建二维数组
awk 'BEGIN{a["a"]["a"]=11;a["a"]["b"]=22;print a["a"]["b"],a["a"]["a"]}'   # 创建关联二>维数组
awk 'BEGIN{a[0,0]=11;a[0,1]=22;print a[0,1],a[0,0]}'
​
# 使用for循环读取所有数组的下表(也就是键)
awk 'BEGIN{a[10]=11;a[88]=22;a["book"]=33;a["work"]="home";for(i in a){print i}}'
awk 'BEGIN{a[10]=11;a[88]=22;a["book"]=33;a["work"]="home";for(i in a){print a[i]}}'    #  打印所有数组下表的值
awk 'BEGIN{a[10]=11;a[88]=22;a["book"]=33;a["work"]="home";for(i in a){print i,a[i]}}'
# 打印下表(键)和值
awk 'BEGIN{a[10]=11;a[88]=22;a["book"]=33;a["work"]="home";for(i in a){print i"="a[i]}}'
​
# 使用if# 判>断pen是否为a的下标(索引,键),这里是值awk 'BEGIN{a[88]=55;a["book"]="pen"; if("pen" in a){print "yes"}else{print "NO"}}' 
awk 'BEGIN{a[88]=55;a["book"]="pen"; if("88" in a){print "yes"}else{print "NO"}}'
df | awk 'NR!=1{disk[$1]=$4}END {for(i in disk) {printf "%-20s %-10s\n",i,disk[i]}}'
​
# awk的for循环使用c语言语法
awk 'BEGIN{for (i=1;i<=5;i++){print i}}'
awk 'BEGIN{for (i=5;i>=1;i--){print i}}'
echo "That is an apple,This is an apple\nHello apple\nIlink apple" > test.txt
awk '{for(i=1;i<=NF;i++){if($i~/apple/)x++}}END{print x}' test.txt    # 默认有多少行执行
多少次,这里是三行,所有执行三次,每执行一次触发for以列来循环if判断是否包含apple,有则x+
+最终x保留app出现的次数
awk '{for(i=1;i<=NF;i++){if($i=="is")x++}}END{print x}' test.txt    # 与上类似,把找的字符变成了is
​
####--------awk的while循环--------------###
#!/bin/bash
awk 'BEGIN{i=1;while(i<=5){print i;i++}}'       # awk使用while循环
awk 'BEGIN{i=10;while(i>=5){print i;i--}}'
​
# 生成测试文件
for i in {1..9}; do     for j in {1..9};     do         echo -n "$i " ;     done;     echo  ; done > test.txt
awk '{i=1;while(i<=NR){printf "%-2d",$i;i++};print ""}' test.txt # 逐行打印,第一行打印>第一列,第二行打印第1和第二列,第三行打印第1,2,3行....最后打印一个空字符表示换行
awk 'BEGIN{i=0;while(i<=5) {i++;if(i==3){continue};print i};print "over" }END{print "end"}' /etc/hosts                                 #当i=3时退出这一次循环继续后面的循环
awk 'BEGIN{i=0;while(i<=5) {i++;if(i==3){break};print i};print "over" }END{print "end"}' /etc/hosts                                    # 当i=3时直接退出BEGIN的循环awk 'BEGIN{i=0;while(i<=5) {i++;if(i==3){exit};print i};print "over" }END{print "end"}' /etc/hosts                   BEGIN                  # 当i=3时直接退出awk,END不受影响
​
​
###-------------内置函数-----------------###
#!/bin/bash
# while函数getline执行直接读取下一行,当列数是1列的则打印第三列;当是6列的直接打印第四列,否则不打印
df -h| awk '{if(NF==1){getline;print $3};if(NF==6){print $4}}'
df -h| awk 'NR==2{print $0;getline;print $0}'   # 先打印第二行的所有,在调用函数getline直接在拉取下一行,并打印改行所有列
echo -e  "Plants are living things\nPlants need sunshine,air and water\nI like to read and draw\nHow many boxes are there?" > test.txt
# 匹配包含air的列并拉取下一行打印,但是下一行没有air但是getline函数不影响后面的执行,而next函数会影响后面的执行所以只会打印noranml line(有多少行执行多少次),{getline和next效果差不多}
awk '/air/{getline;print "next line:",$0}{print "noranml line"}' test.txt 
awk '/air/{next;print "next line:",$0}{print "noranml line"}' test.txt 
​
## system函数在awk内开启一个新shell
awk 'BEGIN{system("ls")}'     
awk 'BEGIN{system("uptime")}'
wk '{system("echo data:"$0)}' test.txt
awk '{system("echo data:"$0 " >> /root/text.txt")}' test.txt # 读取test.txt的文件逐行加data:导入另一个文件
​
## 数值函数
# cos(expr)函数返回expr的cosine值
awk 'BEGIN{print cos(50)}'
awk 'BEGIN{print cos(180)}'
# sin(expr)函数返回expr的sine值
awk 'BEGIN{print sin(45)}'
awk 'BEGIN{print sin(90)}'
​
# sqrt(expr)函数返回expr的平方根
awk 'BEGIN{print sqrt(8)}'
awk 'BEGIN{print sqrt(4)}'
​
# int(expr)函数为取整函数,仅截取整数部分值
awk 'BEGIN{print int(8)}'
awk 'BEGIN{print int(3.9)}'
​
# rand()函数返回0-1的随机数
awk 'BEGIN{print rand()}'
awk 'BEGIN{ for(i=1;i<=5;i++)print rand()}'
awk 'BEGIN{ for(i=1;i<=5;i++)print 100*rand()}' 
awk 'BEGIN{ for(i=1;i<=5;i++)print int(100*rand())}'
​
# srand([expr])函数可以定义新的随机种子,没有expr时则使用时间为随机种子,rand没有新的随机种子则默认一直是那一个随机数
awk 'BEGIN{srand();print rand()}'       # 以时间做随机种子
awk 'BEGIN{srand(777);print rand()}'    # 以数值最随机种子
​
## 内置字符串函数
# lenght([s])函数可以统计字符串s的长度,如果不指定字符串s则默认统计$0所有
awk 'BEGIN{test="hello the world";print length(test)}'
awk 'BEGIN{t[0]="hi";t[1]="the";t[2]="world";print length(t)}'  # 返回数组下标个数
awk 'BEGIN{t[0]="hi";t[1]="the";t[2]="world";print length(t[0])}'  # 返回数组第一个下标的值
awk '{print length()}' /etc/hosts       # 返回每行的字符长度
​
# index(字符串1,字符串2)函数返回字符串2在字符串1中的位置坐标
awk 'BEGIN{test="hello the world";print index(test,h)}'   # h在字符test中的第一个位置
​
# match(s,r)函数根据正则表达式r返回其在字符串s中的位置坐标
awk 'BEGIN{print match("How much? 981$","[0-9]")}'     # 数字在前面的字符串中出现的位置
awk 'BEGIN{print match("How much? 981$","[a-z]")}'     # 小写字符在前面的字符串中出现的位置
awk 'BEGIN{print match("How much? 981$","[A-Z]")}'     # 大写字符在前面的字符串中出现的>位置
​
# tolower(str)函数可以将字符串转换为小写
awk 'BEGIN{print tolower("THIS IS A TEst")}'
awk 'BEGIN{apple="ReD APPLe";print tolower(apple)}'
awk 'BEGIN{apple[0]="ReD APPLe";print tolower(apple[0])}'
​
# toupper(str)函数可以将字符串转换为大写
awk 'BEGIN{apple[0]="ReD APPLe";print toupper(apple[0])}'
​
# split(字符串,数组,分隔符)函数可以将字符串特定的分隔符切片后存储在数组,如果没有指定则默认使用FS的分隔符进行字符串切割
awk 'BEGIN{split("hello the world",test); print test[3],test[2],test[1]}'
awk 'BEGIN{split("hello:the:world",test); print test[1],test[2]}'  # test[2]为空值
awk 'BEGIN{split("hello2the3world",test,"[0-9]"); print test[1]}'  # 以数字为隔符
​
# gsub(r,s,[,t])函数字符串t中所有与正则表达式r匹配的字符串全部替换为s,如果没有指定字符串t,默认对$0进行替换操作
awk 'BEGIN{hi="hello world";gsub("o","O",hi);print hi}'            # 将全部o替换为O
head -1 /etc/passwd | awk '{gsub("[0-9]","**");print $0}'
​
# sub(r,s,[,t])函数与gsub类似,但仅替换第一个匹配的字符串,而不是替换全部
head -1 /etc/passwd | awk '{sub("[0-9]","**");print $0}'
awk 'BEGIN{hi="hello world";sub("o","O",hi);print hi}'
​
# substr(s,i[,n])函数可以对字符串s进行截取,从第i位开始,截取n个字符串,如果n没有指定规则则一直截取到字符串s的末尾位置
awk 'BEGIN{hi="hello world";print substr(hi,2,3)}'                  # 从第二个字符提取后3个字符
awk 'BEGIN{hi="hello world";print substr(hi,2)}'                    # 从第二个字符提取到最后
​
​
### 内置时间函数
# systemtime()返回时间距离1970-01-01 00:00:00有多少秒
awk 'BEGIN{print systime()}'
​
​
### 用户自定义函数
awk 'function myfun(){print "hello"} BEGIN{myfun()}'
awk 'function max(x,y){if(x>y) {print x}else{print y}} BEGIN{max(8,9)}'


###-------使用脚本判断文件中包含的字符------###
#!/bin/bash
echo "That is an apple,This is an apple\nHello apple\nIlink apple" > test.txt
key=$1
awk '{for(i=1;i<=NF;i++){if($i~/'$key'/) print "'$key'的坐标为:"NR"行",i"列"}}' $2
~]# chmod +x awk.sum2.sh 
~]# ./awk.sum2.sh a test.txt
# 位置变量1为要测试的字符串,位置变量2为要判断的文件

其他

###--------------磁盘镜像文件-------------###
#!/bin/bash
# 生成一个容量20G的文件base.img格式qcow2
qemu-img create -f qcow2 base.img 20G
qemu-img info base.img                     # 查看
# 基于 base.img文件创建clone1.qcow2文件,里面内容一致
qemu-img create -f qcow2 -b base.img  clone1.qcow2 20G
qemu-img info clone1.qcow2                 # 查看
​
###---------网络爬虫过滤出种子URL----------###
#!/bin/bash
curl https://tieba.baidu.com/ > tmp.txt   # 下载网页源码
# more tmp.txt                          # 查看网页源码
wc -l tmp.txt                         # 统计文件行数
sed -n '/<img/p' tmp.txt | wc -l      # 过滤包含img的行
sed -i '/<img/!d' tmp.txt             # 将不包含<img的行删除
sed -i 's/.*src="//' tmp.txt          # 再次过滤把src的替换成空
sed -i 's/".*//' tmp.txt              # 再次过滤把"号及后面的内容都替换掉
​
###------网络爬虫过滤出电影的种子URL-------###
#!/bin/bash
URL=https://www.ygdy8.net/index.html
nat=https://www.ygdy8.net
curl -ik $URL > tmp.txt                                  # 过滤出网页链接
sed -i '/^<a href="*"/!d' tmp.txt                     # 继续过滤出链接
awk -F\" '{print $2}' tmp.txt | grep -v \# > tmp2.txt    # 取出url
for i in $(cat tmp2.txt)
do
   echo ${nat}${i} >> tmp3.txt # 添加域名
done
​
​
###-------------日志分析-----------------###
#!/bin/bash
awk '{IP[$1]++}' /usr/local/nginx/logs/access.log      # 把每行的第一列定义成数组下标,>当有多次时++1 
awk '{IP[$1]++}END{for(i in IP){print i,IP[i]}}' /usr/local/nginx/logs/access.log
​
awk '{IP[$9]++}END{for(i in IP){print i,IP[i]}}' /usr/local/nginx/logs/access.log # 可以根据自己的日志设置,我这9列是访问码
# 统计10:00至10:30的日志数据
awk -F"[: /]" '$5":"$6>="10:00"&&$5":"$6<="10:30"' /usr/local/nginx/logs/access-20220529.log
awk -F"[: /]" '$5":"$6>="10:00"&&$5":"$6<="10:30"{print $13}' /usr/local/nginx/logs/access-20220529.log    # 位置根据自己的日志来设置
​
###---------------ss命令-----------------###
#!/bin/bash
ss -at                                  # 显示所有TCP连接状态
ss -atn                                 # 以数字显示所有TCP连接状态
ss -atnp                                # 显示所有以数字TCP连接及进程名状态
ss -anup                                # 显示所有以数字UDP连接及进程名状态
ss -antu                                # 显示所有以数字UDP和TCP连接状态
ss -antuH                               # 不显示标题
ss -antul                               # 仅显示正在listen的信息
ss -an                                  # 显示所有连接的信息
ss -s                                   # 显示数据汇总信息
​
​
###-------------数据库的使用--------------###
#!/bin/bash
mysqladmin -u'root' -p"mysql_P@s5" ping               # 有密码测试
mysqladmin -u'root' -p"mysql_P@s5" -hlocalhost ping 
mysqladmin -u"root" -p"mysql_P@s5" processlist        # 查看谁在用数据库(连接的服务器,库名,什么账户)
## 注意:VARIABLES查看的值可以修改,而STATUS查看到的不能修改
mysql -uroot -pmysql_P@s5 -e "SHOW DATABASES;"        # 非交互式查看数据库   
mysql -uroot -pmysql_P@s5 -e "SHOW VARIABLES LIKE 'max_connections'"      # 非交互式查看数据库的最大并发连接
mysql -uroot -pmysql_P@s5 -e "SHOW VARIABLES LIKE 'max_user_connections'" # 非交互式查看数据库的每个用户最大并发连接
mysql -uroot -pmysql_P@s5 -e "SHOW VARIABLES LIKE '%connections%'"        # 非交互式模糊查看数据库包含connections有关的参数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'Threads_connected'"       # 非交互式查看数据库客户端当前连接数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'Max_used_connections'"    # 非交互式查看数据库客户端最大连接数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'com_select'"              # select被查看到的次数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'com_insert'"              # insert被查看到的次数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'com_update'"              # update指令被执行的次数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'com_delete'"              # delete指令被执行的次数 
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'slow_queries'"            # 数据库慢查询数量
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'Questions'"               # 查看服务器总指令数,不包括存储过程
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'uptime'"                  # 数据库软件启动时间
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'Com_commit'"              # 数据库执行commit指令的次数
mysql -uroot -pmysql_P@s5 -e "SHOW STATUS LIKE 'Com_rollback'"            # 数据库执行rollback指令的次数

;