shell编程--三剑客

  1. 正则表达式
  2. grep
  3. sed  (Stream EDitor:流编辑)
  4. awk

1.正则表达式

        1.1元字符定义及使用场景

        定义:元字符是这样一类字符,它们表达的是不同于字面本身的含义  ;   被vim、sed、awk、grep调用  ;在 mysql、oracle、php、python ,Apache,Nginx...  需要正则

        1.2元字符分类之--基本正则表达式元字符

^      行首定位符
$      行尾定位符
.       匹配任意单个字符
*       匹配前导符0到多次

.*      任意多个字符

[ ]      匹配指定范围内的一个字符

[ - ]     匹配指定范围内的一个字符,连续的范围

[^]      匹配不在指定组内的字符

\         用来转义元字符    (''   ""    \),脱意符

\<      词首定位符

\>       词尾定位符

()        \(..\)            匹配稍后使用的字符的标签

x\{m\}        字符x重复出现m次

x\{m,\}       字符x重复出现m次以上 

x\{m,n\}     字符x重复出现m到n次       
              

        1.3元字符分类之--扩展正则表达式元字符

+       匹配1~n个前导字符

?      匹配0~1个前导字符

a|b       匹配a或b

()        组字符

        1.4示例

grep   love    1.txt         找love

/^love/                以love开头

/love$/                以love结尾

/l.ve/                   l开始,一个任意字符,ve结尾

/lo*ve/                l开始,零个或多个o,ve结尾

/[Ll]ove/              大L 或者小L 开头的  ove

/love[a-z]/            love最后一个小写字母

/love[^a-zA-Z0-9]/                love最后一个(不是字母或者数字),而是符号

/.*/                 所有行          [root@localhost ~]# egrep ".*" 1.txt | wc
/^$/              空行
/^[A-Z]..$/         开头一个大写,最后2个任意字符
/^[A-Z][a-z ]*3[0-5]/        一个大写开头,0到多个小写或空格,3,最后是0-5的一个数字
/[a-z]*\./                        0到多个小写字母,最后一个点
/^ *[A-Z][a-z][a-z]$/                 0到多个空格开头,一个大写,一个小写,再一个小写结尾
/^[A-Za-z]*[^,][A-Za-z]*$/                0到多个字母开头,非逗号,0到多个英文结尾
/\<fourth\>/            找个单词
/\<f.*th\>/               找单词
/5{2}2{3}\./             5两次2三次和一个点
/^[ \t]*$/                 0到多个 ,空格或tab的行
/^#/                        井号开头的行
/^[ \t]*#/                      有0到多个,空格或者tab开头的行,的注释行
:1,$ s/\([Oo]ccur\)ence/\1rence/                  多个r
:1,$ s/\(square\) and \(fair\)/\2 and \1/             换个位置

2.grep

        2.1目的

        过滤,查找文档中的内容

        2.2分类

        egrep         扩展支持正则     ;   fgrep      就不支持正则    ;  grep

        2.3返回值

        0 是找到了     表示成功; 1 是没有    表示在所提供的文件无法找到匹配的pattern  ;2 找到地儿不对

        测试:

        2.4参数        

grep -q 静默

grep -v 取反

grep -R 可以查目录下面的文件

grep -o 只找到这个关键字就可以

grep -B2前两行

grep -A2后两行

grep -C2上下两行

egrep -l 只要文件名

egrep -n 带行号

                

2.sed  (Stream EDitor:流编辑)

        2.1简介

 sed 是一种在线的、非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。

接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;

        2.2格式

        1 sed   选项  命令 文件     sed [options] 'command' file(s)

        2 sed     选项 –f 脚本 文件    sed [options] -f scriptfile file(s)

        2.3返回值

        都是0,对错不管。只有当命令存在语法错误时,sed的退出状态才是非0

        2.4sed和正则表达式

与grep一样,sed在文件中查找模式时也可以使用正则表达式(RE)和各种元字符。正则表达式是括在斜杠间的模式,用于查找和替换,以下是sed支持的元字符。

使用基本元字符集    ^, $, ., *, [], [^], \< \>,\(\),\{\}
使用扩展元字符集    ?, +, |, ( )

使用扩展元字符的方式:
    \+           转义
    sed -r      加-r

        2.5测试

        (1)删除命令:d

sed -r '/root/d' passwd           匹配删除“root”行     

sed -r '3d' passwd                 删除第三行

sed -r '3{d}' passwd               删除第三行

# sed -r '3{d;}' passwd        {存放sed的多个命令} 3{h;d},h暂存空间   

sed -r '3,$d' passwd            删除3到最后一行

sed -r '$d' passwd               删除最后一行

        (2)替换命令:s

sed -r 's/root/aofa/' passwd       把“root“换成”aofo“

 sed -r 's/^root/aofa/' passwd      以root开始的词组,替换成aofa

sed -r 's/root/aofa/g' passwd       全局替换"root"成为"sofo"

sed -r 's/[0-9][0-9]$/&.5/' passwd        查找双数   结尾的词组;&:替换成    双数.5;&有查询结果的含义。

VI中也有类似功能。
    :% s/.*/#&/g                     &:查询结果的含义
    :% s/\(.*\)/#\1/g               每一行;换成
sed -r 's/(mail)/E\1/g' passwd          ()括号组合字符,\1调用括号

sed -r 's#(mail)#E\1#g' passwd           分隔符可以换成井号

        (3)读文件命令:r

sed -r '$r 1.txt' passwd              最后一行,读取新文件1.txt

sed -r '/root/r 1.txt' passwd        正则搜寻root;在root后面读取新文件

***在当前文件中,读取其他文件“部分”内容。

        (4)写文件命令:w(另存为)

sed -r 'w 111.txt' 1.txt           把1.txt全部内容 写入111.txt

sed -r '/root/w 123.txt' passwd           把1.txt 写入111.txt

sed -r '1,5w 123.txt' passwd         把1,5行另存为123.txt

        (5)追加命令:   a(之后)

# sed -r '2a123' passwd        2行后面,加上123行

# sed -r 'a123' passwd         每行后面,都加上123行

sed -r '2a 1111\
> 3333333\
> 444444' passwd                插入段落,请使用\转义掉回车,不要忘了分号结束

        (6)插入命令:   i(之前)

# sed -r '2iaaaaaaaa' passwd       在第二行插入新行aaaaaaaaaa

        (7)替换整行命令:   c

# sed -r '2caaaaaaaa' passwd          把第二行替换成aaaaaaaaa

 sed -r '2c3333\
> 44444' passwd                  一行替换多行  是将一行替换成,多行。

        (8)获取下一行命令:n

# sed -r '/root/{n;d}' passwd           n下一行的意思。找root行,然后下一行,删除

# sed -r '/root/{n;s/bin/ding/g}' passwd      {命令组合}     找到root行,下一行查找替换

        (9)反向选择:      !

# sed -r '2,$!d' passwd   原本的意思是删除第二行到最后一行,加入”!“之后就是删除第一行

        (10)多重编辑 :   e  

# sed -r -e '1,3d' -e '4s/adm/admin/g' passwd    删除1到3行,再把第4行adm换成admin

# sed -r  '1,3d;4s/adm/admin/g' passwd           同上,第4行整行匹配替换

# sed -r '2s/bin/ding/g;2s/nologin/bash/' passwd     第二行bin换成ding,nologin换成bash

# sed -r '2{s/bin/ding/g;s/nologin/bash/}' passwd     括号省了范围

        (11)暂存空间  hHGgx

        

暂存和取用命令:h覆盖暂存空间 H追加暂存空间 g覆盖行 G追加行

# sed -r 'g' passwd         为什么是空白一片

# sed -r 'G' passwd         G是从暂存空间,追加到模式空间。

# sed -r '1h;$G' passwd       第一行覆盖到暂存空间;将暂存空间的内容追加到最后一行

# sed -r '1h;2G;3G;$G' passwd    第一行覆盖到暂存空间,2后面多一行,3后面多一行,10后面多一行

# sed -r '1{h;d};$G' passwd       第一行进入暂存空间,第一行在模式空间中删除,将暂存空间最佳到最后一行。
# sed -r '1h;2,$g' passwd        第一行进入暂存空间;将暂存空间覆盖在,2到最后一行,
# sed -r '1h;2,3H;$G' passwd       第一行进入暂存空间;2,3行追加进攒存空间;将暂存的内容追加到最后一行
# sed -r '4h;5x;6G' passwd          第四行进入暂存空间;将模式空间第五行和暂存空间互换,将暂存空间的内容追加到第六行。

        (12)测试

删除配置文件中#号注释行        # sed -r '/^#/d' /etc/samba/smb.conf

祖传牛皮癣专治老中医         # sed -r '/^[ \t]*#/d' space.txt         删除:以0个和多个空,或者tab,以及#号开始的行

删除配置文件中//号注释行           # sed -r '\Y^[ \t]*//Yd'  space.txt        由于分隔符也是/,所以使用自定义分隔符\Y。

删除无内容空行        # sed -r '/^[ \t]*$/d' space.txt            $即代表空行。

删除注释行及空行另类写法:

        # sed -ri '/^[ \t]*#/d; /^[ \t]*$/d' /etc/vsftpd/vsftpd.conf         都是删除#行和空行

        # sed -ri '/^[ \t]*#|^[ \t]*$/d' /etc/vsftpd/vsftpd.conf        都是删除#行和空行,区别在于使用了     “A|B”     A或B

        # sed -ri '/^[ \t]*($|#)/d' /etc/vsftpd/vsftpd.conf      第三行用括号和$|#进行双选。()进行了组词

修改文件:

        # sed -ri '$a\chroot_local_user=YES' /etc/vsftpd/vsftpd.conf     在最后一行追加

        # sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config       换行c

给文件行添加注释:

        # sed -r '2,6s/^/#/' a.txt         找到2到6行,把开始换成#

        # sed -r '2,6s/(.*)/#\1/' a.txt        ()内容可以被\1引用

        # sed -r '2,6s/.*/#&/' a.txt            &匹配前面查找的内容

多个#换成一个#:

        # sed -r 's/^#*/#/g'   文件名

        # sed -r '30,50s/^[ \t]*#*/#/' /etc/nginx.conf

        # sed -r '2,8s/^[ \t#]*/#/' /etc/nginx.conf

sed中使用外部变量:

        追加变量          # sed -r  "1a$var1" /etc/hosts       第一行后追加变量$var1     注意调用变量时,使用单引号是错误的。

4.awk

        4.1前言

awk 是一种编程语言,用于在linux/unix下对文本和数据进行处理。
数据可以来自标准输入、一个或多个文件,或其它命令的输出。
它支持用户自定义函数和动态正则表达式等先进功能,
awk的处理文本和数据的方式是这样的,
它逐行扫描文件,从第一行到最后一行,
寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),

awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,
分别是Alfred Aho、Peter Weinberger、 Kernighan。

        4.2工作原理

# awk -F: '{print $1,$3}' /etc/passwd
(1)awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符结束

(2)然后,行被:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始,
最多达100个字段

(3)awk输出之后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔
成字段并进行处理。该过程将持续到所有行处理完毕

        4.3语法

        awk   [options]   'commands'      filenames (推荐)

        ==options:    例如:-F 定义输入字段分隔符,默认的分隔符是空格或制表符(tab) 

        ==command(时空):BEGIN{}   {}    END{}
            BEGIN{}         begin发生在行处理前(注意大写)
            {}        行处理时,读一行执行一次
            END{}        行处理后

        4.4内部变量

        (1)FS   输入字段分隔符(默认空格)   

        (2)OFS    输出字段分隔符 

        

        (3)RS      输入记录(行)分隔符,默认换行符 

         (4)ORS       输出记录(行)分隔符,默认换行符

        (5)FNR           多文件独立编号            同下

        (6)NR            多文件汇总编号        

        (7)NF        字段总数      

        4.5格式化输出

        (1)print  函数 

         (2)printf 函数

        语法:

%s 字符类型
%d 数值类型
%f 浮点型,可以定义保留
占15字符
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n
, 逗号,输出字段分隔符

        测试:

        4.6模式(正则表达)和动作

                (1)概念:

任何awk语句都由模式和动作组成。模式部分决定动作语句何时触发及触发事件。
如果省略模式部分,动作将时刻保持执行状态。每一行都会有动作。
模式可以是任何条件语句或复合语句或正则表达式。有模式的话,就是对模式对应的行进行动作。

 模式:可以是条件测试,正则,复合语句
  动作:可以是打印,计算等。                       

                 (2)字符串比较:

字符串比较:
        # awk    '/^root/'     /etc/passwd
        # awk '$0 ~ /^root/' /etc/passwd
        # awk '$0!~/^root/' /etc/passwd
        # awk -F: '$1 ~ /^root/' /etc/passwd 

                (3)数值比较:

目的:
    比较表达式采用对文本进行比较,只有当条件为真,才执行指定的动作。比较表达式使用关系运算符,用于比较数字与字符串。

关系运算符:

        语法
            运算符  含义     示例
        <          小于             x<y
        <=     小于或等于     x<=y
        ==     等于             x==y
        !=     不等于        x!=y
        >=     大于等于         x>=y
        >         大于             x>y

        示例
        # awk -F: '$3 == 0' /etc/passwd 
        # awk -F: '$3 == 1' /etc/passwd 
        # awk -F: '$3 < 10' /etc/passwd
        == 也可以用于字符串判断
        # awk -F: '$7 == "/bin/bash"' /etc/passwd
        # awk -F: '$1 == "alice"' /etc/passwd

算术    运算:

        语法
              + - * / %(模) ^(幂2^3) 

        示例
              # awk -F: '$3 * 10 > 500' /etc/passwd                

        (4)多条件

逻辑操作符和复合模式:

        语法:
        && 逻辑与 a&&b
        || 逻辑或 a||b
        ! 逻辑非 !a

        练习:

        # awk -F: '$1~/root/ && $3<=15'     /etc/passwd
        # awk -F:     '$1~/root/ || $3<=15'         /etc/passwd
        # awk -F:     '!($1~/root/ || $3<=15)'     /etc/passwd

        范围模式:

         语法:
            awk '/从哪里/,/到哪里/' filename

        练习:
         # awk -F: '/adm/,/lpd/' /etc/passwd
        从adm到ldp,显示出来,注意避免匹配重复的字段。

        4.7awk脚本编程

        (1)变量

awk调用变量:

        自定义内部变量 -v  :
    awk -v user=root -F: '$1 == user' /etc/passwd        -v定义变量

        外部变量 “ ‘ ”   :

        1.双引号
        # var="bash"
        # echo "unix script" | awk "{print "123",\"$var\"}"
        123 bash
        注意 awk调用外部变量时,外部使用双引号,内部也使用双引号,但需要转义内部的双引号

        2单引号
        # var="bash"
        # echo "unix script" |awk '{print $1,"'"$var"'"}'
        unix  bash
        注意使用单引号时,内部需要用双引转义

        (2)条件&判断

1.if语句:

        格式:
            {if(表达式){语句;语句;...}}

        示例:  如果$3是0,就说他是管理员

        awk -F: '{if($3==0) {print $1 " is administrator."}}' /etc/passwd

2.if...else语句:

        格式
            {if(表达式){语句;语句;...}else{语句;语句;...}}         {if(){}else{}}

        示例:    如果第三列是0,打印该行第一列,否则打印第七列,登录shell

          awk -F: '{if($3==0){print $1} else {print $7}}' /etc/passwd

        示例:  统计管理员和系统用户数量

        awk -F: '{if($3==0){count++} else{i++}} END{print "管理员个数: "count ; print "系统用户数: "i}' /etc/passwd

3.if...else if...else语句:

        格式:

                if (条件){动作}elseif(条件){动作}else{动作}

                if(){}else if  (){}else if(){}else{}

        示例:  显示出三种用户的信息;管理员:管理员ID为0;内置用户:用户ID<1000普通用户: 用户ID>999

        [root@localhost ~]# awk -F:  '{if($3==0){print $1," is admin "}else if ($3>999){print $1," is user"}else {print $1, " is sofo user"}}'  /etc/passwd

        示例: 统计出三种用户的数量;管理员数量:管理员ID为0;内置用户数量:用户ID<1000普通用户数量: 用户ID>999

        awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print i; print k; print j}' /etc/passwd

        awk -F: '{if($3==0){i++} else if($3>999){k++} else{j++}} END{print "管理员个数: "i; print "普通用个数: "k; print "系统用户: "j}' /etc/passwd

        (3)循环

1.while:

        示例:循环打印10个数字

        awk 'BEGIN{  while(i<=10){print i; i++} }'

        示例:  将每行打印10次

        awk -F: '{ i=1;while(i<=9) {print $0; i++}}'  passwd

2.for:

        示例:循环打印5个数字

        awk 'BEGIN{for(i=1;i<=5;i++){print i} }'

        示例:将每行打印10次

        awk -F: '{ for(i=1;i<=10;i++) {print $0} }' /etc/passwd

        示例:打印每一行的每一列

         awk -F: '{ for(i=1;i<=NF;i++) {print $i} }' passwd                

        (4)数组

1.定义数组:

        示例: 将用户名定义为数组的值,打印第一个值

        # awk -F: '{username[++i]=$1} END{print username[1]}' /etc/passwd

2.数组遍历:

        示例:按索引遍历数组

        #  awk -F: '{username[x++]=$1} END{for(i in username) {print i,username[i]} }' /etc/passwd

        (5)测试

        1. 统计/etc/passwd中各种类型shell的数量

 awk -F: '{shells[$NF]++} END{ for(i in shells){print i,shells[i]} }' /etc/passwd

        $NF 最后一列的字段内容;{}行处理;把统计的对象,作为索引。每次递增。Print i  打印索引;Shells[i]  数组加索引,显示的就是值。

        2. 统计Apache/Nginx日志中的访问前十 <统计日志>

cat  access_log |awk '{ips[$1]++} END{for(i in ips){print i,ips[i]} }' |sort -k2 -rn |head

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值