一、shell 编程-grep
-E 支持扩展正则 -P 支持perl正则 -F 精准过滤,不支持任何特殊字符 -v 反向过滤 -o 只输出匹配到的内容 -i 不区分大小写 -c 统计匹配次数 egrep 支持正则表达式的拓展元字符 (或grep -E) #egrep '[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}' file1.txt
[root@newrain ~]# num1=1 1、运用正则,判断需要[[ ]] [root@newrain ~]# [[ $num1 =~ ^[0-9]+$ ]] && echo "yes" || echo "no" yes [root@newrain ~]# num3=1b1 [root@newrain ~]# [[ $num3 =~ ^[0-9]+$ ]] && echo "yes" || echo "no" no [root@newrain ~]# [[ $num =~ ^[0-9]+\.[0-9]+$ || $num =~ ^[0-9]+$ ]] && echo "yes" || echo "no" //输入的只能是数字(包括小数) 2、* 0或多个 [root@newrain ~]# useradd abrt [root@newrain ~]# grep 'abc*' /etc/passwd abrt:x:1041:1041::/home/abrt:/bin/bash 3、\< 词首定位符号 \>词尾定位符号 [root@newrain ~]# cat jack.txt Jack JACK JAck jackly :% s/\<[Jj]ack\>/123/g 4、^ 以什么开头 [root@newrain ~]# grep '^root' /etc/passwd root:x:0:0:root:/root:/bin/bash 5、$ 以什么结尾 [root@newrain ~]# grep 'bash$' /etc/passwd root:x:0:0:root:/root:/bin/bash confluence:x:1000:1000:Atlassian Confluence:/home/confluence:/bin/bash to:x:1003:1003::/home/to:/bin/bash 6、. 匹配单个字符 [root@newrain ~]# grep 'r..t' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin [root@newrain ~]# grep 'r.t' /etc/passwd operator:x:11:0:operator:/root:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin 7、.* 任意多个字符 [root@newrain ~]# grep 'r.*t' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin systemd-network:x:192:192:systemd Network Management:/:/sbin/nologin polkitd:x:999:997:User for polkitd:/:/sbin/nologin postfix:x:89:89::/var/spool/postfix:/sbin/nologin sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin abrt:x:1041:1041::/home/abrt:/bin/ 8、[] 匹配方括号中的任意一个字符 [root@newrain ~]# grep 'Root' /etc/passwd [root@newrain ~]# grep '[Rr]oot' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin 9、[ - ] 匹配指定范围内的一个字符 [root@newrain ~]# grep [a-z]oot /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin 10、[^] 匹配不在指定组内的字符,取反得意思 [root@newrain ~]# grep '[^0-9]oot' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin [root@newrain ~]# grep '[^0-9A-Z]oot' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin [root@newrain ~]# grep '[^0-9A-Za-z]oot' /etc/passwd [root@newrain ~]# [root@newrain ~]# useradd Root [root@newrain ~]# grep '[a-z]oot' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin Root:x:1042:1042::/home/Root:/bin/bash [root@newrain ~]# grep '^[rc]oot' /etc/passwd root:x:0:0:root:/root:/bin/bash ^在[]内表示取反,^在[]外表示以什么开头 11、\(\)匹配后的标签 [root@newrain ~]# cat file1.txt IPADDR=192.168.1.123 GATEWAY=192.168.1.1 NETMASK=255.255.255.0 DNS=114.114.114.114 :% s#\(192.168.1.\)123#\12# :% s#\(192.\)\(168.\)\(1.\)2#\1\2\35# :% s\(192.\)\(168.\)\(1.\)\(5\)#\1\26.\4# 扩展正则表达式元字符 + 匹配一个或多个前导字符 [a-z]+ove ? 匹配零个或一个前导字符 lo?ve a|b 匹配a或b love|hate (..)(..)\1\2 标签匹配字符 (love)able\1er x{m} 字符x重复m次 o{5 x{m,} 字符x重复至少m次 o{5,} x{m,n} 字符x重复m到n次 o{5,10} 1、+ 匹配一个或多个前导字符 [root@newrain ~]# egrep 'ro+t' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin 2、? 匹配零个或一个前导字符 [root@newrain ~]# egrep 'ro?t' /etc/passwd abrt:x:1041:1041::/home/abrt:/bin/bash 3、a|b 匹配a或b [root@newrain ~]# netstat -anlp|egrep ':80|:22' [root@newrain ~]# egrep 'root|alice' /etc/passwd root:x:0:0:root:/root:/bin/bash operator:x:11:0:operator:/root:/sbin/nologin dockerroot:x:998:995:Docker User:/var/lib/docker:/sbin/nologin 4、x{m} 字符x重复m次 [root@newrain ~]# cat a.txt love love. loove looooove [root@newrain ~]# egrep 'o{2}' a.txt loove looooove [root@newrain ~]# egrep 'o{2,}' a.txt loove looooove [root@newrain ~]# egrep 'o{6,7}' a.txt
二、shell 编程-SED
非交互式编辑器,一次处理一行内容。(流文本编辑器)
-i.bak -i是指在源文件中生效,.bak是可以将原来的文件备份 -f 指定规则文件,如果规则复杂可以使用这个参数 -n 输入的行不再输出,一般和打印p的模式一起使用 -r 支持扩展正则符号 sed "参数" '模式' 参数 1 -f 指定一个规则文件 2 -n 阻止输入行输出 -r 扩展正则 模式 1 s 替换 2 g 整行(也可以是数字,替换第几个) 3 d 删除 4 p 打印 5 a 追加 6 i 是插入示例文件 file1.txt John Daggett, 341 King Road, Plymouth MA Alice Ford, 22 East Broadway, Richmond VA Orville Thomas, 11345 Oak Bridge Road, Tulsa OK Terry Kalkas, 402 Lans Road, Beaver Falls PA Eric Adams, 20 Post Road, Sudbury MA Hubert Sims, 328A Brook Road, Roanoke VA Amy Wilde, 334 Bayshore Pkwy, Mountain View CA Sal Carpenter, 73 6th Street, Boston MA 用Massachusetts替换MA: #前面两个斜杠中是要匹配的内容,可以使用正则,后面两个斜杠中间,是要替换的内容,是纯文本 #sed 's/MA/Massachusetts/' file1.txt 使用多重指令: # sed 's/MA/Massachusetts/ ; s/PA/Pennsylvania/' file1.txt 使用脚本文件: 脚本:namestate s/MA/Massachusetts/ s/PA/Pennsylvania/ s/CA/California/ s/VA/Virginia/ s/OK/Oklahoma/ -f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。 $ sed -f namestate file1.txt 保存输出: $ sed -f namestate file1.txt > newfile.txt 阻止输入行自动显示: $ sed -n 's/MA/Massachusetts/p' file1.txt
sed流编辑器用法及解析
sed: stream editor(流编辑器)的缩写. 它们最常见的用法是进行文本的替换.
[root@newrain ~]# sed '1d' passwd //删除文件的第1行 bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin [root@newrain ~]# sed '1,2d' passwd //删除文件的第1到2行 daemon:x:2:2:daemon:/sbin:/sbin/nologin [root@newrain ~]# cat e.txt /etc/abc/456 etc [root@newrain ~]# sed -r 's#/etc/abc#/var/lib#' e.txt /var/lib/456 etc [root@newrain ~]# cat passwd 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@newrain ~]# sed '2,$d' passwd //删除第2行到最后一行s root:x:0:0:root:/root:/bin/bash [root@newrain ~]# sed '/root/d' passwd //匹配到root,删除此行 bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin [root@newrain ~]# sed '/root/,2d' passwd //匹配到root行,到某一行 daemon:x:2:2:daemon:/sbin:/sbin/nologin [root@newrain ~]# cat -n passwd 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 [root@newrain ~]# sed '1~2d' passwd //删除奇数行 bin:x:1:1:bin:/bin:/sbin/nologin adm:x:3:4:adm:/var/adm:/sbin/nologin sync:x:5:0:sync:/sbin:/bin/sync halt:x:7:0:halt:/sbin:/sbin/halt operator:x:11:0:operator:/root:/sbin/nologin [root@newrain ~]# sed '0~2d' passwd //删除偶数行 root:x:0:0:root:/root:/bin/bash daemon:x:2:2:daemon:/sbin:/sbin/nologin lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
sed可以从stdin中读取内容
$ cat filename | sed 's/pattern/replace_string/'
选项 -i 会使得sed用修改后的数据替换原文件
$ sed -i 's/pattern/replace_string/' filename
g标记可以使sed执行全局替换
$ sed 's/pattern/replace_string/g' filename $ sed 's/pattern/replace_string/gi' filename //忽略大小写替换
g标记可以使sed匹配第N次以后的字符被替换
$ echo "thisthisthisthis" | sed 's/this/THIS/2g'
sed中的分隔符可以替换成别的字符, 因为s标识会认为后面的字符为分隔符
$ sed 's:text:replace_text:' $ sed 's|text|replace_text|'
sed可以利用指令来删除文件中的空行
$ sed '/^$/d' filename
由于在使用 -i 参数时比较危险, 所以我们在使用i参数时在后面加上.bak就会产生一个备份的文件,以防后悔
sed -i.bak 's/pattern/replace_string/' filename
sed如果在脚本中使用的话, 不可避免的要调用变量, 所以以下这种方式可以用来调用变量即' '换成了" "
$ text=hello $ echo "hello world" | sed "s/$text/HELLO/"
在文件中匹配到的部分前后加上一行
sed '/^bin/a\hello nihao/' passwd # 在匹配到开头为bin的行下一行插入内容 sed '/^bin/i\hello nihao/' passwd # 在匹配到开头为bin的行上一行插入内容
三、shell 编程-AWK
awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息 awk处理过程: 依次对每一行进行处理,然后输出 默认分隔符是空格或者tab键
-F 指定输入字段分隔符 -f 指定规则文件 -v 可以给表达式传递变量 awk 参数 'BEGIN{处理之前要做的} {处理内容} END{处理之后的内容}' BEGIN{} {} 行处理前 END{} 行处理 行处理后 [root@newrain ~]# awk 'BEGIN{print 1/2} {print "ok"} END{print "----"}' /etc/hosts # 打印的内容加上双引号 0.5 ok ok ok ok ok ok ---- awk工作原理 awk -F":" '{print $1,$3}' /etc/passwd (1)awk使用一行作为输入,并将这一行赋给变量$0,每一行可称作为一个记录,以换行符结束 (2)然后,行被:分解成字段,每个字段存储在已编号的变量中,从$1开始 (3)awk如何知道空格来分隔字段的呢?因为有一个内部变量FS来确定字段分隔符,初始时,FS赋为空格或者是tab (4)awk打印字段时,将以设置的方法,使用print函数打印,awk在打印的字段间加上空格,因为$1,$3间有一个,逗号。逗 号比较特殊,映射为另一个变量,成为输出字段分隔符OFS,OFS默认为空格 (5)awk打印字段时,将从文件中获取每一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程持续到处理文件结束。默认分隔符是空格或者tab键 awk中的特殊变量: 常用: - NR: 表示记录编号, 当awk将行为记录时, 该变量相当于当前行号 - NF: 表示字段数量, 当awk将行为记录时, 该变量相当于当前列号 难理解: FS(输入字段分隔符) # 以什么符号去分割 OFS(输出字段分隔符) # 以什么分隔符显示 NR(Number of record)行数 FNR按不同的文件分开 RS(输入记录分隔符) ORS(输出记录分隔符) NF 字段个数FS(输入字段分隔符) (filed sign) [root@newrain ~]# awk 'BEGIN{FS=":"} {print $1}' /etc/passwd root bin daemon adm lp sync shutdown halt mail operator games OFS(输出字段分隔符) (output filed sign) [root@newrain ~]# awk 'BEGIN{FS=":";OFS=".."} {print $1,$2}' /etc/passwd root..x bin..x daemon..x adm..x lp..x sync..x shutdown..x NR 表示记录编号, 当awk将行为记录时, 该变量相当于当前行号 [root@newrain ~]# awk -F: '{print NR,$0}' a.txt file1.txt 1 love 2 love. 3 loove 4 looooove 5 6 isuo 7 IPADDR=192.168.6.5 8 hjahj123 9 GATEWAY=192.168.1.1 10 NETMASK=255.255.255.0 11 DNS=114.114.114.114 FNR 表示记录编号, 当awk将行为记录时, 该变量相当于当前行号(不同文件分开) [root@newrain ~]# awk -F: '{print FNR,$0}' a.txt file1.txt 1 love 2 love. 3 loove 4 looooove 5 1 isuo 2 IPADDR=192.168.6.5 3 hjahj123 4 GATEWAY=192.168.1.1 5 NETMASK=255.255.255.0 6 DNS=114.114.114.114RS(输入记录分隔符) [root@newrain ~]# cat passwd 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@newrain ~]# awk -F: 'BEGIN{RS="bash"} {print $0}' passwd root:x:0:0:root:/root:/bin/ bin:x:1:1:bin:/bin:/sbin/nologin daemon:x:2:2:daemon:/sbin:/sbin/nologin ORS(输出记录分隔符) [root@newrain ~]# cat passwd 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@newrain ~]# awk -F: 'BEGIN{ORS=" "} {print $0}' passwd 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@newrain ~]# awk 'BEGIN{ORS="" } {print $0}' /etc/passwd 练习:把一行内容分为多行 [root@newrain ~]# cat d.txt root:x:0:0:root:/root:/bin/bash [root@newrain ~]# awk 'BEGIN{RS=":"} {print $0}' d.txt root x 0 0 root /root /bin/bash
AWK使用理解案例
打印一个文件中的第2列和第3列
$ awk '{ print $2, $3}' filename
打印指定行指定列的某个字符
$ awk -F":" 'NR==3{ print $7 }' /etc/passwd
统计一个文件的行数
$ awk '{ print NR}' filename
在脚本中, 传递变量到awk中
$ var=1000 $ echo | awk -v VARIABLE=$var '{ print VARIABLE }'
指定字段分隔符-F或在BEGIN{ FS=":" }
$ awk -F: '{ print $2, $3 }' filename $ awk 'BEGIN{ FS=":" }{ print $2, $3 }' filename
在awk中使用for循环 (了解)
每行打印两次 [root@newrain ~]# awk -F: '{for(i=1;i<=2;i++) {print $0}}' passwd 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 分别打印每行每列 [root@newrain ~]# awk -F: '{ for(i=1;i<=NF;i++) {print $i}}' passwd
在awk中使用if条件判断 (了解)
显示管理员用户名 [root@newrain ~]# awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd 统计系统用户 [root@newrain ~]# awk -F":" '{if($3>0 && $3<1000){i++}} END{print i}' /etc/passwd