美文网首页
shell编程学习笔记(三)

shell编程学习笔记(三)

作者: dev_winner | 来源:发表于2020-10-29 18:59 被阅读0次
  • sedStream Editor的缩写)是用来处理文件的流编辑器。
  • sed是如何工作的?首先sed读取文件中的一行内容,把其保存在一个临时缓存区中(也称模式空间),然后根据需求处理临时缓冲区中的行内容(不会直接修改原文件),最后把该行发送到屏幕上,反复操作直到读到文件尾为止。sed [选项] '定位+处理动作' 文件名
  • 常用选项:
-e:进行多项处理
-n:取消默认输出(不自动打印模式空间)
-r:使用扩展正则表达式
-i:直接修改源文件(最好不要和处理动作中的 i 或选项 -n一起使用,否则会多打印出处理的语句或者该文件全部内容被替换成要处理的内容)
-f:指定sed脚本的文件名
  • 常用的处理动作
'p':打印
'i':在指定行之前插入内容(类似vim里的大写O)
'a':在指定行之后插入内容(类似vim里的小写o)
'c':替换指定行的所有内容
'd':删除指定行
'r':从另外的文件中读取内容
'w':内容另存为
'&':保存查找串以便在替换串中引用(和\(\)的作用相同)
'=':打印行号
'!':对所选行以外的所有行应用命令,放到行数之后
'q':退出
-------------------------------------------------------------------------
[root@localhost myshell]# sed '' sed_test.txt (对文件什么都不做)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed 'p' sed_test.txt (打印文件中每一行的内容,并且会默认输出文件中每一行内容)
root:x:0:0:root:/root:/bin/bash
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
298374837483
172.16.0.254
172.16.0.254
10.1.1.1
10.1.1.1
[root@localhost myshell]# sed -n 'p' sed_test.txt (打印文件中每一行的内容,取消默认输出文件中每一行内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed -n '2p' sed_test.txt (只打印文件中第二行的内容)
bin:x:1:1:bin:/bin:/sbin/nologin
[root@localhost myshell]# sed -n '1,5p' sed_test.txt (打印文件中第1到第5行的内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# sed -n '$p' sed_test.txt (只打印文件中最后一行的内容)
10.1.1.1
[root@localhost myshell]# sed '2ihello world' sed_test.txt (在第二行之前插入 hello world 语句)
root:x:0:0:root:/root:/bin/bash
hello world
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed 'ihello world' sed_test.txt (在每一行前插入 hello world 语句)
hello world
root:x:0:0:root:/root:/bin/bash
hello world
bin:x:1:1:bin:/bin:/sbin/nologin
hello world
daemon:x:2:2:daemon:/sbin:/sbin/nologin
hello world
adm:x:3:4:adm:/var/adm:/sbin/nologin
hello world
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
hello world
298374837483
hello world
172.16.0.254
hello world
10.1.1.1
[root@localhost myshell]# sed '3i\  ("\":转移换行符)
> hello\
> world\
> 888' sed_test.txt
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
hello
world
888
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed '$a99999' sed_test.txt (在最后一行后面插入99999)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
99999
[root@localhost myshell]# sed '$chello world' sed_test.txt (将文件中最后一行内容替换为 hello world 字符串)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
hello world
[root@localhost myshell]# sed '/^adm/czhangsan' sed_test.txt (将以adm开头的行内容修改为 zhangsan 字符串)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
zhangsan
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed 'czhangsan' sed_test.txt (将每一行内容修改为 zhangsan 字符串)
zhangsan
zhangsan
zhangsan
zhangsan
zhangsan
zhangsan
zhangsan
zhangsan
[root@localhost myshell]# sed '1,5czhangsan' sed_test.txt (将第1~5行内容压缩为 只有 zhangsan 这一字符串)
zhangsan
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed '4d' sed_test.txt (删除第4行内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed '1,4d' sed_test.txt (删除第1~4行的内容)
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed 'd' sed_test.txt (删除文件中所有行内容)
[root@localhost myshell]# sed -r '/([0-9]{1,3}\.){3}[0-9]{1,3}/d' sed_test.txt (-r 使用扩展正则表达式来删除文件中所有的ip地址)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
[root@localhost myshell]# sed '$d' sed_test.txt (删除最后一行内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
  • 对文件进行搜索替换:sed [选项] 's/搜索的内容/替换的内容/动作' 需要处理的文件。其中,s表示search搜索;斜杠/表示分隔符,可自定义;动作一般是打印p和全局替换g
[root@localhost myshell]# sed -n 's/root/ROOT/p' sed_test.txt 
ROOT:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# sed -n 's/root/ROOT/gp' sed_test.txt 
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
[root@localhost myshell]# cat -n sed_test.txt 
     1  #root:x:0:0:root:/root:/bin/bash
     2  #bin:x:1:1:bin:/bin:/sbin/nologin
     3  #daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4  adm:x:3:4:adm:/var/adm:/sbin/nologin
     5  lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6  298374837483
     7  172.16.0.254
     8  10.1.1.1
[root@localhost myshell]# sed -n 's/^#//gp' sed_test.txt 
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
[root@localhost myshell]# sed -n 's@/sbin/nologin@zhangsan@pg' sed_test.txt (自定义分隔符为 @,避免发生歧义)
#bin:x:1:1:bin:/bin:zhangsan
#daemon:x:2:2:daemon:/sbin:zhangsan
adm:x:3:4:adm:/var/adm:zhangsan
lp:x:4:7:lp:/var/spool/lpd:zhangsan
[root@localhost myshell]# sed -n '5s#/sbin/nologin#zhangsan#p' sed_test.txt (只对第5行内容进行修改)
lp:x:4:7:lp:/var/spool/lpd:zhangsan
[root@localhost myshell]# sed -n '1,5s/^/#/gp' sed_test.txt (将第1~5行内容的行首加上注释符号)
#root:x:0:0:root:/root:/bin/bash
#bin:x:1:1:bin:/bin:/sbin/nologin
#daemon:x:2:2:daemon:/sbin:/sbin/nologin
#adm:x:3:4:adm:/var/adm:/sbin/nologin
#lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# sed -n 's#\(10.1.1.\)1#\1254#gp' sed_test.txt (修改ip地址)
10.1.1.254
[root@localhost myshell]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1 LVS_DEVEL
[root@localhost myshell]# sed '3r /etc/hosts' sed_test.txt (在sed_test.txt文件中第三行后读取 /etc/hosts 文件中的所有内容并插入,r表示从另外的文件中读取内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
127.0.0.1 LVS_DEVEL
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed -n '1,5w test1.txt' sed_test.txt(将sed_test.txt文件中第1~5行的内容另存为test.txt文件中,w表示另存为新的文件)
[root@localhost myshell]# ll test1.txt 
-rw-r--r--. 1 root root 183 10月 30 09:23 test1.txt
[root@localhost myshell]# sed -n 's/^adm/#&/gp' sed_test.txt (&表示查找关键字:adm)
#adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost myshell]# sed -n 's/\(^adm\)/\1#/gp' sed_test.txt (使用 \(\) 保留查找关键字)
adm#:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost myshell]# sed -n '/root/p' sed_test.txt (找出包含 root 关键字的所有行)
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# sed -ne '/root/p' -ne '/root/=' sed_test.txt (-e表示进行多项处理,=表示打印行号,注意:e放在选项最后)
root:x:0:0:root:/root:/bin/bash
1
[root@localhost myshell]# sed -n '/root/=;/root/p' sed_test.txt (用 ; 隔开,不用加选项-e,进行多项处理)
1
root:x:0:0:root:/root:/bin/bash
[root@localhost myshell]# sed -n '1,5!p' sed_test.txt (除了第1~5行内容不打印外,其他行的内容都要打印一下)
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed '/adm/q' sed_test.txt (处理到包含 adm 的行就退出处理操作)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
[root@localhost myshell]# sed -r '/^#|^$/d' sed_test.txt (-r表示使用扩展正则表达式,删除以 # 开头或空行的行内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
[root@localhost myshell]# sed -i 's/root/ROOT/g' sed_test.txt (只将文件中的root关键字全部替换成ROOT)
[root@localhost myshell]# cat sed_test.txt 
ROOT:x:0:0:ROOT:/ROOT:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
298374837483
172.16.0.254
10.1.1.1
  • sed结合正则表达式的用法:sed [选项] 处理动作 | 正则表达式 | 地址定位 文件名。定址用于决定对哪些行进行编辑,地址的形式可以是数字、正则表达式或二者的结合。若没有指定地址,sed命令将处理输入文件中的所有行。
正则表达式 说明 备注
/key/ 查询包含关键字的行 sed -n '/root/p' sed_test.txt
/key1/,/key2/ 匹配包含两个关键字之间的行 sed -n '/^adm/,/^mysql/p' sed_test.txt
/key/,x 从匹配关键字的行开始到文件第x行之间的行(包含关键字所在行) sed -n '/^ftp/,7p'
x,/key/ 从文件的第x行开始到与关键字的匹配行之间的行 sed -n '3,/^adm/p' sed_test.txt
x,y! 不包含x到y行 sed -n '2,10!p' sed_test.txt
/key/! 不包括关键字的行 sed -n '/bash$/!p' sed_test.txt
[root@localhost myshell]# head /etc/passwd > sed_test.txt (重写)
[root@localhost myshell]# tail -3 /etc/passwd >> sed_test.txt (追加)
[root@localhost myshell]# cat -n sed_test.txt 
     1  root:x:0:0:root:/root:/bin/bash
     2  bin:x:1:1:bin:/bin:/sbin/nologin
     3  daemon:x:2:2:daemon:/sbin:/sbin/nologin
     4  adm:x:3:4:adm:/var/adm:/sbin/nologin
     5  lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
     6  sync:x:5:0:sync:/sbin:/bin/sync
     7  shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
     8  halt:x:7:0:halt:/sbin:/sbin/halt
     9  mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    10  operator:x:11:0:operator:/root:/sbin/nologin
    11  user05:x:1015:1019::/home/user05:/bin/bash
    12  yunwei:x:1016:1020::/home/yunwei:/bin/bash
    13  apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
[root@localhost myshell]# sed -n '/^lp/,/^mail/p' sed_test.txt 
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@localhost myshell]# sed -nr '/^lp|^mail/p' sed_test.txt 
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
[root@localhost myshell]# sed -n '/sync/,8p' sed_test.txt (打印包含sync的行到第8行的内容)
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
[root@localhost myshell]# sed -n '/sync/,2p' sed_test.txt (只打印匹配到关键字的行,因为默认按行升序打印)
sync:x:5:0:sync:/sbin:/bin/sync
[root@localhost myshell]# sed -n '3,/^adm/p' sed_test.txt (打印第3行到匹配关键字的行的内容)
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
  • 指定sed脚本文件对某个文件进行修改:sed -f scripts.sh [选项] filename。sed脚本文件的注意事项:
1、脚本文件中的内容是一个sed的命令行清单。
2、在每行的末尾不能有任何空格、制表符(tab)或其它文本。
3、若在一行中有多个命令,则应用分号分隔开。
4、不要用引号保护命令。
5、#号开头表示注释。
6、脚本第一行:#!/bin/sed -f
------------------------------------------------------------------------------
[root@localhost myshell]# cat scripts.sh 
#!/bin/sed -f
 #转义换行,在第2行之后插入******************
2a\ 
******************
# 从第2行到最后一行搜索关键字 stu,并将其修改为user 
2,$s/stu/user/
$a\
we inster new line
# 在小写字母开头的行前添加注释符号
s/^[a-z].*/#&/ 
[root@localhost myshell]# sed -f scripts.sh -i passwd (-i表示修改源文件)
[root@localhost myshell]# cat passwd 
#stu3:x:509:512::/home/user3:/bin/bash
#user4:x:510:513::/home/user4:/bin/bash
******************
#user5:x:511:514::/home/user5:/bin/bash
we inster new line
  • 若在正则表达式中出现特殊字符(^$.*/[]),则需要以前导\符号做转义,如:sed '/\$foo/p' file
  • awk 是一种处理文本文件的语言,是一个强大的文本分析工具。
  • awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行预期操作。
  • awk分别代表其作者(Alfred AhoBrian KernighanPeter Weinberger)姓氏的第一个字母。
  • awk的使用方式:①命令行模式awk [选项] '命令部分' 文件名 。注意:若引用shell变量则必须把单引号改成双引号,其他情况下必须使用单引号。②脚本模式:脚本第一行:#!/bin/awk -f,该脚本中只编写awk引号里的命令清单,不要用引号保护命令,多个命令用分号间隔。脚本执行方式:awk [选项] -f awk脚本文件名 要处理的文件名。例如:awk -f awk.sh filenamesed -f sed.sh -i filename./awk.sh filename./sed.sh filename
  • 常用选项:
-F:定义字段分割符号,默认的分隔符是空格
-v:定义变量并赋值
  • awk命令部分说明:①使用正则表达式或地址定位;②{awk语句1;awk语句2;...},注意:awk命令语句间用分号间隔;③BEGIN...END....
'/root/{awk语句}'               sed中:'/root/p'
'NR==1,NR==5{awk语句}'           sed中:'1,5p'
'/^root/,/^ftp/{awk语句}'         sed中:'/^root/,/^ftp/p'
'{print $0;print $1}'             sed中:'p'
'NR==5{print $0}'               sed中:'5p'
'BEGIN{awk语句};{处理中};END{awk语句}'
'BEGIN{awk语句};{处理中}'
'{处理中};END{awk语句}'
  • awk内部相关变量:
变量 说明 备注
$0 当前处理行的所有记录
$1,$2,$3...$n 文件中每行以间隔符号(默认是空格)分割的不同字段 awk -F: '{print $1,$3}'
NF 当前行记录的字段数(列数) awk -F: '{print NF}'
$NF 最后一列 $(NF-1)表示倒数第二列
FNRNR 行号
FS 定义字段分隔符 'BEGIN{FS=":"};{print $1,$3}'
OFS 定义输出字段的分隔符,默认为空格 'BEGIN{OFS="\t"};print $1,$3}'
RS 输入记录的分隔符,默认为换行符 'BEGIN{RS="\t"};{print $0}'
ORS 输出记录的分隔符,默认为换行符 'BEGIN{ORS="\n\n"};{print $1,$3}'
FILENAME 当前输入的文件名
[root@localhost myshell]# awk '{print $0}' awk_test.txt (打印文件中所有行的内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
......
[root@localhost myshell]# awk 'NR==1,NR==5{print $0}' awk_test.txt (只打印第1~5行的内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# awk 'NR==1 || NR==5{print $0}' awk_test.txt (使用逻辑运算符,只打印第1行和第5行的内容)
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# awk 'NR>=3 && NR<=5{print $0}' awk_test.txt (只打印第3~5行的内容)
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# awk -F: '{print $1,$NF}' awk_test.txt (以冒号分隔,打印第一列和最后一列)
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
......
[root@localhost myshell]# awk -F: '{print $1,$NF,$(NF-1)}' awk_test.txt (以冒号分隔,打印第一列和倒数两列)
root /bin/bash /root
bin /sbin/nologin /bin
daemon /sbin/nologin /sbin
......
[root@localhost myshell]# awk -F: '{print NF}' awk_test.txt (以冒号分隔,打印列数)
7
7
7
......
[root@localhost myshell]# awk 'NR==1,NR==5' awk_test.txt (不使用 print 这样也可以输出第1~5行的内容)
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
[root@localhost myshell]# awk -F: '/root/{print $1,$NF}' awk_test.txt (匹配含有 root 关键字的所有行,并将每一行以冒号分隔,输出其第一列和最后一列内容)
root /bin/bash
operator /sbin/nologin
[root@localhost myshell]# awk -F: '{print $1,$NF}' awk_test.txt (输出字段的分隔符默认为空格)
root /bin/bash
bin /sbin/nologin
daemon /sbin/nologin
......
[root@localhost myshell]# awk -F: 'BEGIN{OFS="@"};{print $1,$NF}' awk_test.txt (定义输出字段的分隔符为 @,输出第一列和最后一列)
root@/bin/bash
bin@/sbin/nologin
daemon@/sbin/nologin
......
[root@localhost myshell]# awk 'BEGIN{FS=":";OFS="@"};{print $1,$NF}' awk_test.txt (-F: 参数可用BEGIN{FS=":"}替换)
root@/bin/bash
bin@/sbin/nologin
daemon@/sbin/nologin
[root@localhost myshell]# awk 'BEGIN{FS=":"};{print $1"+++++++++++++++"$NF}' awk_test.txt (定义分隔符和输出分隔符)
root+++++++++++++++/bin/bash
bin+++++++++++++++/sbin/nologin
daemon+++++++++++++++/sbin/nologin
......
[root@localhost myshell]# awk 'BEGIN{FS=":"};{print "用户名是:"$1"******shell的解析器为:"$NF}' awk_test.txt 
用户名是:root******shell的解析器为:/bin/bash
用户名是:bin******shell的解析器为:/sbin/nologin
用户名是:daemon******shell的解析器为:/sbin/nologin
[root@localhost myshell]# cat awk_test.txt 
root:x:0:0:root:/root:/bin/bash hello   world
bin:x:1:1:bin:/bin:/sbin/nologin    zhangsan
daemon:x:2:2:daemon:/sbin:/sbin/nologin # 从 daemon 开始看作整个字符串
adm:x:3:4:adm:/var/adm:/sbin/nologin
......
[root@localhost myshell]# awk -F: 'BEGIN{RS="\t"};{print $1}' awk_test.txt (每当读取到 \t 就处理该字符串,把该字符串以冒号分隔并输出第一列的内容)
root
hello
world
bin
zhangsan
daemon
[root@localhost myshell]# awk 'BEGIN{ORS="\t"};{print $0}' awk_test.txt (将输出记录的分隔符替换为制表符,默认为换行符)
root:x:0:0:root:/root:/bin/bash hello   world   bin:x:1:1:bin:/bin:/sbin/nologin    zhangsan    daemon:x:2:2:daemon:/sbin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin    sync:x:5:0:sync:/sbin:/bin/sync shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown    halt:x:7:0:halt:/sbin:/sbin/halt    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin  operator:x:11:0:operator:/root:/sbin/nologin    user05:x:1015:1019::/home/user05:/bin/bash  yunwei:x:1016:1020::/home/yunwei:/bin/bash  apache:
  • awk的工作原理:awk -F: '{print $1,$3}' /etc/passwd
1、awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也称为一个记录,以换行符(RS)结束;
2、每行被间隔符:(默认为空格或制表符)分解成字段或域,每个字段存储在已编号的变量中,从$1开始。初始时,内部变量FS赋值为空格;
3、awk使用print函数打印字段,字段间以空格分隔,因为$1,$3之间是一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格;
4、awk处理完一行后,将从文件中获取下一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行都处理完毕。
  • awk格式化输出函数:print(类似于echo,换行)和printf(类似于echo -n,不换行)。格式化形式:①%s:字符类型,%15s表示占位15个字符;②%d:数值类型;③-:表示左对齐,默认是右对齐;④printf默认不会在行尾自动换行,要换行需加\n
[root@localhost myshell]# date | awk '{print "Month:"$2"\nYear:"$1}' 
Month:10月
Year:2020年
[root@localhost myshell]# awk -F: '{printf "|%-15s|%-10s|%-15s\n",$1,$2,$3}' awk_test.txt 
|root           |x         |0              
|bin            |x         |1              
|daemon         |x         |2        
......
[root@localhost myshell]# awk -v NUM=3 -F: '{print $NUM}' awk_test.txt (定义变量并打印以冒号分隔的第三列)
0
1
2
......
[root@localhost myshell]# awk -v NUM=3 -F: '{print NUM}' awk_test.txt (打印变量 NUM 的值,注意不加 $ )
3
3
3
......
[root@localhost myshell]# awk -v NUM=3 'BEGIN{print NUM}'
3
  • awkBEGIN...END...的使用:​①BEGIN:表示在程序开始前执行;​②END:表示在所有内容处理完后执行;③​ 用法:'BEGIN{开始处理之前};{处理中};END{处理结束后}'
[root@localhost myshell]# awk -F: 'BEGIN{print "登录SHELL\t\t家目录\n*******************"};{print $NF"\t\t"$(NF-1)};END{print "*******************"}' awk_test.txt 
登录SHELL     家目录
*******************
/bin/bash   hello   world       /root
/sbin/nologin   zhangsan        /bin
/sbin/nologin       /sbin
/sbin/nologin       /var/adm
......
*******************
  • awk结合正则表达式一起使用:
运算符 说明
== 等于
!= 不等于
> 大于
< 小于
>= 大于或等于
<= 小于或等于
~ 匹配
!~ 不匹配
! 逻辑非
&& 逻辑与
|| 逻辑或
[root@localhost myshell]# awk 'NR>=1 && NR<=5 && $0 ~ /^root/{print $0}' awk_test.txt (从第1~5行中找出以 root 开头的行并打印其内容,~表示匹配)
root:x:0:0:root:/root:/bin/bash hello   world
[root@localhost myshell]# ifconfig ens32 | awk 'NR==2{print $2}' 
192.168.211.146
[root@localhost myshell]# ifconfig ens32 | grep broadcast | awk -F'[: ]+' '{print $3}'
192.168.211.146
  • awk命令部分使用if条件语句:{ if(表达式) {语句1;语句2;...} }
[root@localhost myshell]# awk -F: '{ if($3>=500 && $3<=60000) {print $1,$3} }' passwd 
stu3 509
stu4 510
stu5 511
[root@localhost myshell]# awk 'BEGIN{ if('$(id -u)' == 0) {print "cur user is admin"} }'  # 注意:$(id -u) 要用单引号包起来
cur user is admin
  • awk命令部分使用if...else条件语句:{ if(表达式) {语句1;语句2;...} else { 语句3;语句4;...} }
[root@localhost myshell]# awk -F: '{ if($3>=500 && $3 != 65534) {print $1"是普通用户"} else {print $1,"不是普通用户"}}' passwd 
stu3是普通用户
stu4是普通用户
stu5是普通用户
[root@localhost myshell]# su - stu1
上一次登录:二 10月 27 08:46:52 CST 2020pts/1 上
[stu1@localhost ~]$ awk 'BEGIN{if( '$(id -u)' >= 500 && '$(id -u)' != 65534 ) {print "是普通用户"} else {print "不是普通用户"}}'
是普通用户
  • awk命令部分使用if...else if...else条件语句:{ if(表达式1) {语句1;语句2;...} else if(表达式2) {语句3;语句4;...} else if(表达式3) {语句5;语句6;...} else {语句7;语句8;...} }
[root@localhost myshell]# awk -F: '{ if($3==0) {print $1,":是管理员"} else if($3>=1 && $3<=499 || $3==65534 ) {print $1,":是系统用户"} else {print $1,":是普通用户"}}' /etc/passwd 
root :是管理员
bin :是系统用户
daemon :是系统用户
......
[root@localhost myshell]# awk -F: '{ if($3==0) {i++} else if($3>=1 && $3<=499 || $3==65534 ) {j++} else {k++}};END{print "管理员个数为:"i "\n系统用户个数为:"j"\n普通用户的个数为:"k }' /etc/passwd
管理员个数为:1
系统用户个数为:31
普通用户的个数为:28
  • awk命令部分使用for循环语句:
[root@localhost myshell]# awk 'BEGIN { for(i=1;i<=5;i++) {print i} }'
1
2
3
4
5
[root@localhost myshell]# sum=0;for((i=1;i<=10;i+=2));do let sum=$sum+$i;done;echo $sum;
25
[root@localhost myshell]# awk 'BEGIN{sum=0;for(i=1;i<=10;i+=2) sum+=i;print sum}'
25
[root@localhost myshell]# for((i=1;i<=10;i+=2));do echo $i;done | awk '{sum+=$0};END{print sum}'
25
  • awk命令部分使用while循环语句:
[root@localhost myshell]# i=1;while (($i<=5));do echo $i;let i++;done
1
2
3
4
5
[root@localhost myshell]# awk 'BEGIN { i=1;while(i<=5) {print i;i++} }'
1
2
3
4
5
[root@localhost myshell]# awk 'BEGIN{i=1;sum=0;while(i<=5) {sum+=i;i++}; print sum }'
15
  • awk命令部分使用嵌套循环语句:
[root@localhost myshell]# awk 'BEGIN{ for(y=1;y<=5;y++) {for(x=1;x<=y;x++) {printf x} ;print } }'
1
12
123
1234
12345
  • awk命令部分使用算术运算
[root@localhost myshell]# awk 'BEGIN{print 2**3}'
8
[root@localhost myshell]# awk 'BEGIN{print 2/3}'
0.666667
[root@localhost myshell]# awk 'BEGIN{print 2.9+3}'
5.9
  • 统计系统中各种类型的shell
[root@localhost myshell]# awk -F: '{ shells[$NF]++ };END{for (i in shells) {print i,shells[i]} }' /etc/passwd
/bin/sync 1
/bin/bash 18
/sbin/nologin 39
/sbin/halt 1
/sbin/shutdown 1
  • 统计网站访问状态:
[root@localhost myshell]# ss -antp | grep 80 | awk '{states[$1]++};END{for(i in states){print i,states[i]}}'
LISTEN 1
[root@localhost myshell]# ss -an | grep :80 |awk '{states[$2]++};END{for(i in states){print i,states[i]}}' | sort -k2 -rn
LISTEN 1

相关文章

网友评论

      本文标题:shell编程学习笔记(三)

      本文链接:https://www.haomeiwen.com/subject/rnflvktx.html