您的位置:新葡亰496net > 服务器网络 > 新葡亰496net:Linux正则表达式sed,练习题四

新葡亰496net:Linux正则表达式sed,练习题四

发布时间:2019-06-20 08:52编辑:服务器网络浏览(175)

    shell脚本(一)基础知识,shell脚本基础知识

    shell

    一、简介

    1.作用:与内核进行交互

    2.语言类型:解释性语言,给内核解释用

    3.脚本中第一行内容:

    #!/bin/bash                       这是shell脚本的第一行内容,表示用bash这个解释器去解释下面的内容

    #!/bin/sh                            这也可以是shell脚本的第一行内容,表示用sh这个解释器去解释下面的内容

    #!/usr/bin/env bash        env表示使用相对路径,自动找bash解释器所在位置。可以解决不同版本的系统bash不一定在/usr/bin/bash这个路径下的问题

    4.为了使脚本方便其他人阅读,一般会在开头加上作者、创建时间、邮箱、版本、描述等内容,可以使用以下设置快捷键的方法在脚本中增加这些信息

    vim /etc/vimrc

    map <F4> ms:call WESTOS()<cr>'s
    function WESTOS()
            call append(0,"######################################")
            call append(1,"# Author     :vaon                   #")
            call append(2,"# Create Date:".strftime("%Y-%m-%d")."             #")
            call append(3,"# Email      :[email protected]         #")
            call append(4,"# Version    :1.0                    #")
            call append(5,"# Description:                       #")
            call append(6,"######################################")
            call append(7,"                          ")
            call append(8,"#!/usr/bin/env bash")
    endfunction

    #map表示影射-->按F4时调用(呼叫)WESTOS函数

    #0代表第一行,1第二行...

    #黄色部分strftime是一个系统自带的函数,表示显示当前时间   .是分隔符,表示这个函数与其他两段内容互不影响

    #下面是设定函数的方法:

        Fucton 函数名()

        内容

        Endfunction

    然后创建一个脚本使用F4键就会在脚本最前面自动加上以下内容:

    二、基础知识

    1.变量的声明${a}b

    设定a=1

    echo $a 会出现1,

    但echo $ab就不会出现1b,因为系统把ab当成一个变量了。

    可以echo ${a}b,会出现1b,把作为一个已定义的1

    2.转义、弱引用、强引用

    1)表示转义

    echo ###不会出现结果,但是加上 echo ###就会出现###

    2)“”表示弱引用,也可以输出###

    3)‘’表示强引用,可以输出###

    4)强引用和弱引用的区别

    例如 $  !    ``  这些强引用会把他们当作普通内容打印到屏幕上

    而弱引用会把他们当成系统变量,执行变量里的内容

    还例如在弱引用中`hostname`表示执行hostname命令

    而在强引用中表示输出`hostname`这个内容

    3.diff、patch

    1)diff

    【1】.

    [[email protected] mnt]# cat file1
    abcd
    1234
    [[email protected] mnt]# cat file2
    abcd
    [[email protected] mnt]# diff file1 file2
    2d1
    < 1234
    #表示file1删除1234就和file2一样了

    【2】.比较目录

    diff -r 目录一 目录二

    2)打补丁

    建立hello文件:

    vim hello

    westos

    建立hello.new文件:

    vim hello.new

    westos

    456

    安装自动更新工具包:

    yum install patch -y

    将hello.new与hello文件比较,多出的内容做成hello.path补丁包:

    diff -u hello hello.new > hello.path

    用path补丁包去更新hello文件:

    patch hello hello.path

    查看hello文件,已经被更新成和hello.new一样了:

    cat hello

    westos

    456

    注:如果patch后面加上-b参数表示在更新的同时备份原文件为hello.orig

    4.grep

    首先建立一个文件:

    [[email protected] mnt]# vim /mnt/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
    hello
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    games:x:12:100:games:/usr/games:/sbin/nologin
    test:ROOT:test
    test:test:root
    test:root:test
    test:roottest:test

    1)查找包含root子段的行

    [[email protected] mnt]# grep root /mnt/passwd
    root:x:0:0:root:/root:/bin/bash
    test:test:root
    test:root:test
    test:roottest:test

    2)查找包含root子段的行,不区分大小写

    [[email protected] mnt]# grep -i root /mnt/passwd
    root:x:0:0:root:/root:/bin/bash
    test:ROOT:test
    test:test:root
    test:root:test
    test:roottest:test

    3)只要root开头的

    [[email protected] mnt]# grep -i ^root /mnt/passwd
    root:x:0:0:root:/root:/bin/bash

    4)只要root结尾的

    [[email protected] mnt]# grep -i root$ /mnt/passwd
    test:test:root

    5)以root开头和结尾的行都不要。-E表示后面两个条件同时筛选,-v表示不要筛选出的行

    [[email protected] mnt]# grep -i root /mnt/passwd|grep -i -E "^root|root$" -v
    test:ROOT:test
    test:root:test
    test:roottest:test

    6)表示只要包含只有root子段的行,root前后只要有字母都不要,如roottest这行就不要

    [[email protected] mnt]# grep -i "<root>" /mnt/passwd|grep -i -E "^root|root$" -v
    test:ROOT:test
    test:root:test
    问题:

    查看所有能登陆系统的用户

    解答:

    [[email protected] mnt]# grep "<bash>" /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    可见只有root能登陆
    7)grep -n 表示显示搜索出的字符串所在行号

    [[email protected] mnt]# grep -n hello /mnt/passwd
    4:hello

    8)gep -n2 表示显示搜索出的行以及它的上面2行和下面2行,并且显示各自在文件中的行号

    注:如果-n和2之间有空格则表示除了上面显示的内容还会在每行开头显示出文件名

    [[email protected] mnt]# grep -n2 hello /mnt/passwd
    2-bin:x:1:1:bin:/bin:/sbin/nologin
    3-daemon:x:2:2:daemon:/sbin:/sbin/nologin
    4:hello
    5-mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    6-games:x:12:100:games:/usr/games:/sbin/nologin

    9)grep -B2 表示显示搜索出的行以及这行的上两行内容
    [[email protected] mnt]# grep -B2 hello /mnt/passwd
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    hello
    10)grep -A2 表示下两行

    [[email protected] mnt]# grep -A2 hello /mnt/passwd
    hello
    mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
    games:x:12:100:games:/usr/games:/sbin/nologin
    11)表示搜索/mnt目录下包含root字符的文件
    [[email protected] mnt]# grep -r hello /mnt/
    /mnt/passwd:hello

    5.cut

    用法:cut -d 分隔符 -f 第几列 文件

    -c指定字符

    -d指定分隔符

    -f指定第几列

    cut -d : -f 2 /mnt/psswd     #以:为分隔符,显示passwd文件第二列

    cut -d : -f 2,7 /mnt/psswd   #,表示第二和第七列,如果是-表示2到第7列

    cut -c 3 /mnt/passwd      #显示第三列的字符,不使用分隔符

    cut -c 1,3 /mnt/passwd     #显示一和三列的字符,不使用分隔符

    题目:

    显示eth0网卡的ip

    解答:

    [[email protected] mnt]# ifconfig eth0|grep "<inet>"|cut -d " " -f 10
    172.25.254.1

    6.awk

    -v表示给变量赋予内容:

    [[email protected] mnt]# name=hello
    [[email protected] mnt]# awk -F : -v name=$name 'BEGIN {print name} {print $1}END {print "end"}' /mnt/passwd
    hello
    root
    bin
    daemon
    hello
    mail
    games
    test
    test
    test
    test
    end
    7.sed

    -i      #这个参数表示写入文件

    sed ‘s/old/new/g’ passwd       #将passwd文件中的所有old字符替换为new

    sed ‘s/old/new/g’ passwd       #将passwd文件中的所有old字符替换为new,并写入passwd文件

    sed ‘2,5s/old/new/g’ passwd      #替换2到5行

    sed ‘/adm/,/gdm/s/old/new/g’ passwd   #从adm字符一直到gdm字符的内容中将old替换为new

    sed -e ‘s/old/new/g’ -e ‘s/old1/new1/g’ passwd   #将old替换为new同时将old1替换为new1

    sed 5d passwd    #删除第5行

    sed 5p passwd    #复制第5行

    sed -n 5p passwd    #只显示第5行

    -p    #表示直接将 sed 的动作写在一个档案内, -f filename 则可以执行 filename 内的sed 动作

    vim file

    s/sbin/westos/g
    s/nologin/linux/g

    sed -f file passwd

    题目:

    将httpd服务端口改为8080

    解答:

    ############################
    # Author     :vaon                           #
    # Create Date:2017-12-16             #
    # Email      :[email protected]       #
    ############################

    #!/bin/bash
    PORT=`grep ^Listen /etc/httpd/conf/httpd.conf`
    sed "s/$PORT/Listen $1/g" -i /etc/httpd/conf/httpd.conf
    systemctl restart httpd

    8.设置变量

    1)临时设置(环境级)

    在当前环境生效,当前环境关闭,变量失效

    先看一个例子:

    [[email protected] mnt]# a=1
    [[email protected] mnt]# echo $a
    1
    [[email protected] mnt]# vim test.sh
    #!/bin/bash
    echo $a
    [[email protected] mnt]# sh test.sh 

    [[email protected] mnt]#

    #由于a=1是在当前使用的shell里面赋的值,当进入脚本执行时,脚本使用的是子shell,这个子shell中并没有设定a=1,所以结果为空

    [[email protected] mnt]# export a=1
    [[email protected] mnt]# sh test.sh
    1

    #可以临时设定a=1给所有shell,一旦登出就会失去这个临时设定

    2)永久设置

    【1】.系统级

    对所有用户生效

    [[email protected] mnt]# vim /etc/profile

    export a=1

    [[email protected] mnt]# source /etc/profile

    [[email protected] mnt]# logout
    Connection to 172.25.254.1 closed.
    [[email protected] Desktop]# ssh [email protected]
    [email protected]'s password:
    Last login: Sat Dec 16 09:12:16 2017 from 172.25.254.10
    [[email protected] ~]# cd /mnt/
    [[email protected] mnt]# sh test.sh
    1

    #这样所有shell都可以使用a=1这个变量,登出系统再登陆依然存在a=1

    【2】.用户级

    只针对配置过的用户生效,其他用户无法使用

    vim /root/.bash_profile

    export a=1

    source /root/.bash_profile

    现在a=1只对root用户生效

    9.将脚本加到系统命令中去
    [[email protected] mnt]# vim /etc/profile

    export PATH=$PATH:/mnt

    注:这里同样存在系统级或用户级的设置,在这里使用的是系统级设置。如果只允许root可以设置/root/.bash_profile文件

    [[email protected] mnt]# source /etc/profile

    [[email protected] mnt]# chmod x test.sh 

    然后退出/mnt目录,直接把test.sh脚本当成系统命令去执行,发现也可以:

    [[email protected] mnt]# cd
    [[email protected] ~]# test.sh
    1
    10.命令别名

    1)使用别名

    [[email protected] ~]# vim /etc/bashrc
    alias kan='cat'             #表示执行'kan'的时候相当于执行'cat'命令

    [[email protected] ~]# source /etc/bashrc

    查看别名列表:

    [[email protected] ~]# alias

             ...

    alias kan='cat'

             ...

    执行kan这个单词就相当于执行cat命令

    [[email protected] ~]# kan /mnt/test.sh
    ######################################
    # Author     :vaon                   #
    # Create Date:2017-12-16             #
    # Email      :[email protected]         #
    ######################################
                              
    #!/bin/bash
    echo $a
    2)删除别名
    删除/etc/bashrc中的alias kan='cat'

    然后在删除kan信息:

    unalias kan

    现在查看alias列表,里面已经没有kan的信息了

    11.*和@区别

    vim test.sh

    #!/bin/bash
    echo '$1 Is' $1
    echo '$2 Is' $2
    echo '$3 Is' $3
    echo '$* Is' $*
    echo '$# Is' $#
    echo '[email protected] Is' [email protected]
    [[email protected] mnt]# sh test.sh 1 2 3
    $1 Is 1                                                   #显示第1个字符
    $2 Is 2                                                   #显示第1个字符
    $3 Is 3                                                   #显示第1个字符
    $* Is 1 2 3                                             #显示所有字符
    $# Is 3                                                   #新葡亰496net,显示最后一个字符
    [email protected] Is 1 2 3                                           #显示所有字符
    *和@都表示所有内容,但实际上一个是所有内容方到“”里面。而@是每个数据都加引号

    $*   “1 2 3”

    &@  “1” “2” “3”

    12.shell脚本中函数的定义

    READ()

    {

            echo hello word

    }

    13.变量对比

    1)test

    2)[ ]

    [[email protected] mnt]# a=1
    [[email protected] mnt]# b=1
    [[email protected] mnt]# test "$a" == "$b" && echo yes || echo no
    yes
    [[email protected] mnt]# [ "$a" == "$b" ] && echo yes || echo no
    yes
    3)[ 条件1 -a 条件2 ] 表示条件1和2都满足
    4)[ 条件1 -o 条件2 ] 表示条件1和2任一个满足

    5)[ 条件1 -eq 条件2 ]  等于

    6)[ 条件1 -ne 条件2 ]  不等于

    7)[ 条件1 -gt 条件2 ]  大于

    8)[ 条件1 -ge 条件2 ]  大于等于

    9)[ 条件1 -lt 条件2 ]  小于

    10)[ 条件1 -le 条件2 ]  小于等于

    [[email protected] mnt]# [ "$a" -eq "$b" ] && echo yes || echo no
    yes

    11)[ -n ]   变量内容不为空

    12)[ -z ]    变量内容为空

    [[email protected] mnt]# a=8
    [[email protected] mnt]# [ -n "$a" ] && echo yes || echo no
    yes
    [[email protected] mnt]# [ -z "$a" ] && echo yes || echo no
    no

    13)[ -b ]  是否为块设备文件

    14)[ -c ]  是否为字符设备文件

    [[email protected] mnt]# [ -b /dev/sda ] && echo yes || echo no
    yes
    [[email protected] mnt]# [ -c /dev/vfio/vfio ] && echo yes || echo no
    yes

    15)[ -f ]  是否为常规文件

    16)[ -S ]  是否为套接字文件

    17)[ -L  ]  是否为链接文件

    18)[ -d ]  是否为目录

    19)[ -e ] 文件是否存在

    20)[ -r ]  是否可读

    21)[ -w ]  是否可写

    22)[ -x ]  是否可执行

    18)[ filename1 -nt filename2 ]  如果 filename1 比 filename2 新,则为真

    19)[ filename1 -ot filename2 ]  如果 filename1 比 filename2 旧,则为真

    [[email protected] mnt]# touch file
    [[email protected] mnt]# [ /mnt/check_ip -ot file ] && echo yes || echo no
    yes

    题目:

    显示输入的文件类型

    解答:

    #!/bin/bash
    [ -e $1 ] && (
            [ -f $1 ] && echo "$1 Is File"
            [ -d $1 ] && echo "$1 Is Directory"
            [ -b $1 ] && echo "$1 Is Block File"
            [ -L $1 ] && echo "$1 Is Link"
            [ -S $1 ] && echo "$1 Is Socket"
    )
    14.四则运算

    15.语句

    case语句:
    并发的去匹配所有条件,所有条件同一时间去配置,效率比if语句高

    if语句是逐行去匹配,第一行不匹配再去匹配下一行,效率较低

    exit 退出脚本。后面加数字1|0则表示退出后$?的值为1|0

    break 退出循环

    练习题四,

    由于上篇文章总结的不是很详细,有很多方面并未涉及到shell各个方面,所以发表此文章对shell做了更全面的总结:

    Linux正则表达式sed 详述

    sed、awk工具可以实现文本替换并且把替换的文本输出到屏幕上
    sed和awk都是流式编辑器,是针对文档的行来操作的。sed通常用来替换操作。

    示例的文本内容,以下操作根据此文本。
    [[email protected] ~]# cat test.txt 
    rot:x:0:0:rot:/rot:/bin/bash
    root:x:0:0:root:/root:/bin/bash
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    rooooot:x:0:0/roooooot:/bin/bash
    11111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    1、打印某一行
    sed -n 'n'p filename 单引号内的n是一个数字,表示第几行;p也可以写到引号内;

    示例,打印passwd第3-5行;

    [[email protected] ~]# sed -n '3,5'p /etc/passwd
    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

    打印所有行

    [[email protected] ~]# sed -n '1,$'p /etc/passwd

    打印某一行,并且要显示行号,需要和grep一起使用;

    [[email protected] ~]# grep -n '.*' test.txt | sed -n '1'p
    1:rrt

    2、打印包含某个字符串的行

    字符串需要用/ /括起来;grep中的特殊符号^ $ . * 同样适用于sed中。
    [[email protected] ~]# sed -n '/root/'p /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin

    打印包含/sbin/nologin的行,/需要进行脱意;
    [[email protected] ~]# sed -n '//sbin/nologin/'p passwd 
    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

    打印以d开头的行;打印以in结尾的;打印r与o字母中间有2个任意字符的;打印包含2个o及多个o的行;
    [[email protected] ~]# sed -n '/^d/'p test.txt 
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    [[email protected] ~]# sed -n '/in$/'p test.txt 
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    [[email protected] ~]# sed -n '/r..o/'p test.txt
    rooooot:x:0:0/roooooot:/bin/bash
    [[email protected] ~]# sed -n '/ooo*/'p test.txt
    root:x:0:0:root:/root:/bin/bash
    rooooot:x:0:0/roooooot:/bin/bash

    3、-e可以实现多个行为
    [[email protected] ~]# sed -e '1'p -e '/111/'p -n test.txt 
    rot:x:0:0:rot:/rot:/bin/bash
    11111111111111111111111111111111

    可以用-e写多个;-e相当于传送带,先匹配最前面的打印,再匹配后面的打印,所以第一行会打印2次;

    [[email protected] ~]# sed -e '/root/p' -e '/bash/p' -n 1.txt
    root:x:0:0:root:/root:/bin/bash
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    user1:x:500:500::/home/user1:/bin/bash
    user2:x:501:501::/home/user2:/bin/bash

    -e后面也可以用;分号;-n不能写到-e的后面,可以写在-e的前面或最后面;
    [[email protected] ~]# sed -e '/root/p;/bash/p' -n 1.txt
    root:x:0:0:root:/root:/bin/bash
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    user1:x:500:500::/home/user1:/bin/bash
    user2:x:501:501::/home/user2:/bin/bash

    4、删除某行或者多行

    ‘d’ 这个字符就是删除的动作了,不仅可以删除指定的单行以及多行,而且还可以删除匹配某个字符的行,另外还可以删除从某一行一直到文档末行。

    示例,删除第一行;删除1-3行;删除包含root关键词的行;删除第3行到最后一行所有行;
    [[email protected] ~]# sed '1'd test.txt 
    root:x:0:0:root:/root:/bin/bash
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    rooooot:x:0:0/roooooot:/bin/bash
    11111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    [[email protected] ~]# sed '1,3'd test.txt 
    rooooot:x:0:0/roooooot:/bin/bash
    11111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    [[email protected] ~]# sed '/root/'d test.txt
    rot:x:0:0:rot:/rot:/bin/bash
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    rooooot:x:0:0/roooooot:/bin/bash
    11111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    [[email protected] ~]# sed '3,$'d test.txt 
    rot:x:0:0:rot:/rot:/bin/bash
    root:x:0:0:root:/root:/bin/bash

    5、替换字符或替换字符串

    示例,替换第一行字母r为R;替换1-2行中ot为to;替换所有行中ot为to;
    [[email protected] ~]# sed '1s/r/R/g' test.txt 
    RRt
    [[email protected]ia ~]# sed '1,2s/ot/to/g' test.txt 
    rto:x:0:0:rto:/rto:/bin/bash
    roto:x:0:0:roto:/roto:/bin/bash
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    rooooot:x:0:0/roooooot:/bin/bash
    11111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    [[email protected] ~]# sed 's#ot#to#g' test.txt 
    rto:x:0:0:rto:/rto:/bin/bash
    roto:x:0:0:roto:/roto:/bin/bash
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    rooooto:x:0:0/roooooto:/bin/bash
    11111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    与vim编辑器里面替换一样的命令格式,s代表替换,g代表全局,不加g的话只替换行的第一个;可以使用# @作为分隔符。

    1s代表只替换第一行;1,3s代表第一行到第三行;不加行数的话默认为全部行。

    示例,删除文档中所有的数字's/[0-9]//g'  如删除文档中所有的字母's/[a-zA-Z]//g'删除所有的数字和字母's/[0-9a-zA-Z]//g'
    [[email protected] ~]# sed 's/[0-9]//g' test.txt 
    rot:x:::rot:/rot:/bin/bash
    root:x:::root:/root:/bin/bash
    daemon:x:::daemon:/sbin:/sbin/nologin
    rooooot:x::/roooooot:/bin/bash
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    示例,删除文档中所有的字母
    [[email protected] ~]# sed 's/[a-z]//g' 1.txt 
    ::0:0:/://
    ::11:0::/://
    ::11:0::/://
    ::0:0:/://
    1111111111111111111111111111111

    示例,删除文档中不是英文字母的(数字和特殊符号)
    [[email protected] ~]# sed 's/[^a-z]//g' 1.txt 
    rotxrotbinbash
    operatorxoperatorrootsbinnologin
    operatorxoperatorroootsbinnologin
    rooootxroooootbinbash
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    示例,删除文档中不是数字的(英文字母和特殊符号)

    [[email protected] ~]# sed 's/[^0-9]//g' 1.txt 
    00
    110
    110
    00
    1111111111111111111111111111111

    示例,把文档中的小写字母全部替换为大写字母 's/[a-z]/u&/g'
    [[email protected] ~]# sed 's/[a-z]/u&/g' 1.txt 
    ROT:X:0:0:/ROT:/BIN/BASH
    OPERATOR:X:11:0:OPERATOR:/ROOT:/SBIN/NOLOGIN
    OPERATOR:X:11:0:OPERATOR:/ROOOT:/SBIN/NOLOGIN
    ROOOOT:X:0:0:/ROOOOOT:/BIN/BASH
    1111111111111111111111111111111
    AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

    示例,把文档中的大写字母全部替换为小写字母 's/[A-Z]/l&/g'

    [[email protected] ~]# sed 's/[A-Z]/l&/g' 1.txt 
    rot:x:0:0:/rot:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    operator:x:11:0:operator:/rooot:/sbin/nologin
    roooot:x:0:0:/rooooot:/bin/bash
    1111111111111111111111111111111
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    替换的同时加-n p 打印特定的行;

    [[email protected] ~]# sed -n '1s/[a-z]/u&/g'p 1.txt 
    ROT:X:0:0:/ROT:/BIN/BASH

    6、调换二个字符串的位置
    sed -r 's/([^:] )(:.*:)([^:] $)/321/'
    [^:]非冒号,不是冒号的所有字符
    -r, --regexp-extended  在脚本中使用扩展正则表达式; 加r选项的意思为后面不用再加脱意 
    ( )括号括起来是分段的意思,
    321    是代表3调换1,后面的内容调换到前面

    示例,aa与ff调换;加-r选项不用加脱意符号;不加-r ( )括号左右都需要加脱意;调换多行用最后一个;
    [[email protected] ~]# cat 1.txt 
    aa:bb:cc:dd:ee:ff
    [[email protected] ~]# sed -r 's/(aa)(.*)(ff)/321/' 1.txt
    ff:bb:cc:dd:ee:aa
    [[email protected] ~]# sed 's/(aa)(.*)(ff)/321/' 1.txt 
    ff:bb:cc:dd:ee:aa
    [[email protected] ~]# sed -r 's/([^:] )(:.*:)([^:] $)/321/' 1.txt 
    ff:bb:cc:dd:ee:aa

    示例,rot与/bin/bash进行调换
    [[email protected] ~]# grep 'rot' test.txt
    rot:x:0:0:rot:/rot:/bin/bash
    [[email protected] ~]# grep 'rot' test.txt |sed 's/(rot)(.*)(/bin/bash)/321/'
    /bin/bash:x:0:0:rot:/rot:rot
    [[email protected] ~]# grep 'rot' test.txt |sed -r 's/(rot)(.*)(/bin/bash)/321/'
    sed:-e 表达式 #1,字符 18:“s”的未知选项
    [[email protected] ~]# grep 'rot' test.txt |sed -r 's/(rot)(.*)(/bin/bash)/321/'
    /bin/bash:x:0:0:rot:/rot:rot

    加-r  后()内的/bin/bash 也还需要脱意才可以;

    -i 选项    直接替换字符,并且保存原文件里面。使用i选项前,记得备份原文件。

    [[email protected] ~]# sed -r -i 's/([^:] )(:.*:)([^:] $)/321/' 1.txt 
    [[email protected] ~]# cat 1.txt 
    ff:bb:cc:dd:ee:aa

    在sed命令中引入shell变量

    Linux下Shell编程——sed命令基本用法

    Unix文本处理工具之sed 

    sed 高级用法

    sed命令详解与示例

    本文永久更新链接地址:

    详述 sed、awk工具可以实现文本替换并且把替换的文本输出到屏幕上 sed和awk都是流式编辑器,是针对文档的行来操作的。...

    咱有什么说什么,说实在的,这部分我感觉是liunx中最乱的地方,也是最不好学的,也是能看出人最专业的地方,明白我的意思了吧,,,,自己体会。新葡亰496net 1

    第1章 练习题

     

    数组 declare

    1.1 每天晚上 12 点,打包站点目录/var/www/html 备份到/data 目录下(最好每次备份按时间生成不同的备份包)

    文章版权:

    定义变量的类型

    1.1.1 测试命令

    [[email protected] ~]# cd / && tar zcf /data/www_`date %F`.tar.gz  var/www/html

    环境变量路径:

    declare 选项 变量名=值

    1.1.2 写入脚本中

    [[email protected] /]# cat /server/scripts/www.sh

    cd / && tar zcf /data/www_`date %F`.tar.gz  var/www/html

    [[email protected] ~]# set   //查看到的是局部变量和全局变量2种

    选项有

    1.1.3 测试脚本

    [[email protected] ~]# sh /server/scripts/www.sh

    [[email protected] ~]# env  //查看系统的全局环境变量

    -i 整形的变量

    1.1.4 写入定时任务

    [[email protected] /]# crontab -l |tail -2

    #### backup /var/www/html dir

    00 00  * * *  /bin/sh  /server/scripts/www.sh >/dev/null 2>&1

    [[email protected] ~]# echo $PATH  //查看系统环境变量路径

    -r 只读的变量 定义就不可以修改了

    1.1.5 检查执行结果

    [[email protected] ~]# ll /data/

    total 16

    -rw-r--r--  1 root root 154 Sep 11 09:44 www_2017-09-11.tar.gz

    [[email protected] ~]# export $PATH  //也可以使用export查看环境变量路径

    -x 系统环境变量

    1.2 每周 六、日 上午 9:00和下午 14: 00  来老男孩这里学习(执行程序/server/script/oldboy.sh代替学习)。

    00 9,14 * * 0,6  /bin/sh /server/scripts/oldboy.sh >/dev/null 2>&1

                         0表示周日

                         6表示周六

    [[email protected] ~]# export PATH=$PATH:/date/  //临时添加/date目录到环境变量路径下

    -a 数组变量 想把多个变量定义成一个组

    1.3 描述下列路径的内容是做什么的。

    /etc/sysctl.conf            系统内核的配置文件

    /etc/rc.local               开机自启动

    /etc/hosts                  ip与域名的对应关系 ,解析主机名

    /etc/fstab                  开机自动挂载

    /var/log/secure             用户登陆信息,主要查看其中的Failed

    要想重启主机后还生效就要编辑环境配置文件root/.bashec或/root/.bash_profile与/etc/profile文件,想要立刻生效可以使用命令:

    ---------

    1.4 请说出下列 grep 正则表达式的含义

    ^         以...开头的行

    $         以...结尾的行

    .(点号)    任意一个字符

             在转义字符  n t

    *           前一个字符练习出现0次或1次以上

    {n,m}       前一个字符连续出现,至少n次,最多m

    [^t]         取不包含t的

    ^[^t]        以不是t的开头

    注:.bash_profile文件支队系统当前用户生效

    [[email protected] ~]# declare -i a=1 b=2

    1.5  排除文件中的空行和空格

    [[email protected] ~]# source .bash_profile  

    [[email protected] ~]# declare -i c=$a*$b

    1.5.1 文件的内容

    [[email protected] ~]# cat -A mun.txt

    znix1$

    znix2$

    znix3$

    $

    znix4$

          $

    znix5$

          $

    znix6$

    [[email protected] ~]# ls –a    可以查看到这2个文件

    [[email protected] ~]# echo $c

    1.5.2 egrep方法

    找出空行  -v参数排除

    [[email protected] ~]# egrep -n "^ *$" mun.txt

    4:

    6:     

    8:     

    10:

    14:

    [[email protected] ~]# egrep -n  "^$|^ $" mun.txt

    4:

    6:     

    8:     

    10:

    14:

     

    2

    1.5.3 awk方法

    [[email protected] ~]# awk '!/^[ ]*$/' mun.txt

    znix1

    znix2

    znix3

    znix4

    znix5

    znix6

    脚本的执行:

    ---------

    1.6 把passwd.txt 第一列取出来

    sh script    //这种方法script不需要可执行权限

    创建数组

    1.6.1 文件内容

    [[email protected] ~]# cat passwd.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

    sync:x:5:0:sync:/sbin:/bin/sync

    ./ script          //必须具有可执行权限

    [[email protected] ~]# declare -a teaname

    1.6.2 排除思想

    [[email protected] ~]# egrep "^[^:] " passwd.txt  -o

    root

    bin

    ……

    . script           //这种方法script也不需要可执行权限

    ----------

    1.6.3 sed方法

    [[email protected] ~]# sed -r 's#(^.*)(:x.*:)(.*)#321#g' passwd.txt

    /bin/bash:x:0:0:root:/root:root

    /sbin/nologin:x:1:1:bin:/bin:bin

    ……

    排除不是以 :开头的行

    [[email protected] ~]# sed -r 's#(^[^:] )(.*:)(/.*$)#321#' passwd.txt

    /bin/bash:x:0:0:root:/root:root

    /sbin/nologin:x:1:1:bin:/bin:bin

    ……

                           

    查看数组

    1.6.4 awk方法

    awk中的变量:

    -vOFS=":"

    OFS 的内容就是 , 的内容

    awk在显示每一列内容的时候,每一列之间的分隔符

    -v 修改和创建awk可以使用的变量

    [[email protected] ~]# awk -F: -vOFS=":" '{print $NF,$2,$3,$4,$5,$6,$1}' passwd.txt

    /bin/bash:x:0:0:root:/root:root

    /sbin/nologin:x:1:1:bin:/bin:bin

    ……

    区分局部变量和全局变量

    [[email protected] ~]# declare -a

    1.7 vi/vim命令、快捷键

     含义

    命令

    退出保存

    :wq

    退出并强制保存,!为强制的意思

    :wq!

    强制退出,不保存 

    :q!

    另存为

    :q  /tmp/****

    光标移动到文件的最后一行

    G

    光标移动到文件的第一行

    gg

    光标移动到文件的100行

    100gg 100G :100

    从光标所在位置将光标移动到当前行的开头

    0  ^

    从光标所在位置将光标移动到当前行的结尾

    $

    删除当前行的内容

    dd

    删除当前行到文件的最后一行的内容 

    dG

    删除当前行到文件的第一行的内容

    dgg

    粘贴

    p

    粘贴10次

    10p

    复制

    yy

    取消上一次的动作

    u

    删除一行

    dd

    / 搜索内容

    继续向下搜索              n

    继续向上搜索              N

    向上搜索 

    ?

    取消对找到的内容的高亮显示

    :noh

    [[email protected] ~]# str=1000   //局部变量

    ------

    1.7.1 编辑services定位到第100行把这一行复制到文件的最后一行粘贴10次。

    100gg

    yy

    G

    10p

     

    数组赋值 添加信息)

    1.8 授权 oldboy 目录及其子目录 755 的权限。

    chmod -R 755 oldboy

    [[email protected] ~]# echo $str

    数组名 [元素下标]=值

    1.9 把 oldboy 目录及其子目录的属主改为 oldboy,组改为 root。

    chown  oldboy.lodboy oldboy.txt

    1000

    ----------

    1.9.1 修改时可能发生的错误

    [[email protected] ~]# id oldboy

    uid=500(oldboy) gid=501(incahome) groups=501(incahome)

    [[email protected] ~]# chown oldboy.oldboy oldboy-new.txt

    [[email protected] znix ~]# chown oldboy.oldboy num.txt

    chown: invalid user: `oldboy.oldboy'

    检查oldboy用户是否存在,检查oldbo这个用户组是否存在

    去编辑一个脚本:

    给数组添加内容

    1.10 描述下 umask 的作用.

    umask管理着linux默认的权限

    实例1-1 当umask为021时

    file 权限为644

     666-021 001=644

    dir 权限为 756

     777-021=756

    # vim bianliang.sh

    [[email protected] ~]# teaname[0]=yzs

    1.11 每天打包备份 /etc/rc.local /etc/hosts /etc/services 到 /backup目录。

    #!/bin/bash

    [[email protected] ~]# teaname[1]=xly

    1.11.1 测试命令

    [email protected] ~]# cd / && tar zcf /backup/file`date %F`.tar.gz  etc/rc.local  etc/hosts etc/services

      [email protected] /]# ll /backup/file2017-09-11.tar.gz

    -rw-r--r-- 1 root root 127455 Sep 11 15:41 /backup/file2017-09-11.tar.gz

    echo $str

    [[email protected] ~]# teaname[2]=lili

    1.11.2 写入脚本

    [[email protected] /]# cat /server/scripts/file.sh

    cd / && tar zcf /backup/file`date %F`.tar.gz  etc/rc.local  etc/hosts etc/services

    [[email protected] ~]# bianliang.sh  //我们定义的变量,但是通过脚本却不能输出

    [[email protected] ~]# declare -a

    1.11.3 测试脚本

    [[email protected] /]# sh /server/scripts/file.sh

    [[email protected] /]# ll /backup/file2017-09-11.tar.gz

    -rw-r--r-- 1 root root 127455 Sep 11 15:44 /backup/file2017-09-11.t

    [[email protected] /]# cat /server/scripts/file.sh

     

    declare -a BASH_ARGC='()'

    1.11.4 写入定时任务

    ### beifen zhongyaowenjan

    00 00 * * * /bin/sh /server/scripts/file.sh >/dev/null 2>&1

    [[email protected] 新葡亰496net:Linux正则表达式sed,练习题四。~]# export str   //添加到全局变量中

    declare -a BASH_ARGV='()'

    1.11.5 测试定时任务

    [[email protected] ~]# date -s '23:59:29'

    Mon Sep 11 23:59:29 CST 2017

    [[email protected] ~]# ll /backup/file2017-09-1*

    -rw-r--r-- 1 root root 127455 Sep 11 15:44 /backup/file2017-09-11.tar.gz

    -rw-r--r-- 1 root root 127455 Sep 12  2017 /backup/file2017-09-12.tar.gz

    [[email protected] ~]# bianliang.sh   //再次使用完全ok

    declare -a BASH_LINENO='()'

    第2章 回顾课程

    1000

    declare -a BASH_SOURCE='()'

    2.1 定时任务

    要想完全的清除某个全局变量:

    declare -ar BASH_VERSINFO='([0]="3" [1]="2" [2]="25" [3]="1" [4]="release" [5]="i386-redhat-linux-gnu")'

    每隔 2 个小时将/etc/services 文件打包备份到/tmp 下(最好每次备份成不同的备份包)

    # unset str  清除全局变量

    declare -a DIRSTACK='()'

    2.1.1 测试命令

    [[email protected] ~]# cd / && /bin/tar zcf /tmp/ser_`date %F_%H`.tar.gz  etc/services

    #env   可以查看到所有全局变量

    declare -a FUNCNAME='()'

    2.1.2 放入脚本中

    [[email protected] ~]# cat /server/scripts/ser.sh

    cd / && /bin/tar zcf /tmp/ser_`date %F_%H`.tar.gz  etc/services

    && || 的用法:(参数的比对)

    declare -a GROUPS='()'

    2.1.3 测试脚本

    [[email protected] ~]# sh /server/scripts/ser.sh

    && 条件符合要求才会执行后面的动作

    declare -a PIPESTATUS='([0]="0")'

    2.1.4 写入定时任务

    [[email protected] ~]# crontab -l |tail -2

    #backup /etc/services

    00 */2 * * * /bin/sh /server/scripts/bak-ser.sh >/dev/null 2>&1

    ||    条件不符合要求时才会执行后面的动作

    declare -a teaname='([0]="yzs" [1]="xly" [2]="lili")'

    2.1.5 检查定时任务是否成功

    1)是否打包成功,看看文件里面是否有追加的信息

    2)查看定时任务日志 /var/log/cron

    //查看/ect目录下是否有/grub.conf文件,有则输出yes,无则输出no。

    ------------

    2.2 无法连接linux

    [[email protected] ~]# [ -f /etc/grub.conf ] && echo yes  || echo no 

    [[email protected] ~]# serip=(1.1.1.1 2.2.2.2 3.3.3.3)

    2.2.1 道路是否通畅

    ping ip地址

    实例2-1 无法ping通的解决办法:

    服务器的ip地址是否正确

    服务器网卡是否启动,即ONBOOT是否为yes

    系统网卡的配置

    实例2-2 VMware相关的:

    vmware-5个服务是否启动

    vmware配置-网卡是否连接

    查看你vmware网卡的vmnet8 是否已经启动

    Yes        

    [[email protected] ~]# declare -a |grep serip

    2.2.2 是否有人劫财劫色

    查看 iptables selinux是否关闭

    查看/shellscripts/hello.sh是否可执行,可执行则输入yes,否则就赋予它可执行权限

    declare -a serip='([0]="1.1.1.1" [1]="2.2.2.2" [2]="3.3.3.3")'

    2.2.3 是否有人提供服务

    实例2-3 看22端口是否开启

    方法一: telnet 10.0.0.200 22

    方法二: ss -lntup |grep 22

    实例2-4 进程是否在运行

    ps -ef |grep sshd

    [[email protected] shellscripts]# [ -x /shellscripts/hello.sh ] && echo yes || chmod x /shellscripts/hello.sh

    ---------------

    2.3 linux无法上网怎么办

    [[email protected] shellscripts]# ls

    输出数组元素

    2.3.1 ping 域名

    域名无法ping 通

    [[email protected] ~]# ping centos.houzhaoshun.cn

    ping: unknown host centos.houzhaoshun.cn

     

    hello.sh  ipadd.sh  logmess_clean.sh 

    [[email protected] ~]# echo ${serip[1]}

    2.3.2 ping  外网ip

    可以ping 通

    [[email protected] ~]# ping 123.206.66.149

    PING 123.206.66.149 (123.206.66.149) 56(84) bytes of data.

    64 bytes from 123.206.66.149: icmp_seq=1 ttl=128 time=63.1 ms

    64 bytes from 123.206.66.149: icmp_seq=2 ttl=128 time=60.5 ms

    [[email protected] shellscripts]# hello.sh

    2.2.2.2

    2.3.3 检查dns配置文件

    [[email protected] ~]# cat /etc/resolv.conf

    hello world!   

    输出全部元素

    2.3.4 修改配置文件

    修改完成重启网卡,生效

    [[email protected] ~]# service network restart

    Shutting down interface eth0:                              [  OK  ]

    Shutting down loopback interface:                          [  OK  ]

    Bringing up loopback interface:                            [  OK  ]

    Bringing up interface eth0:  Determining if ip address 10.0.0.201 is already in use for device eth0...

                                                               [  OK  ]

    “”和‘’与 ` ` 在shell变量中的区别       

    [[email protected] ~]# echo ${serip[@]}

    2.4 检查一个软件是否按照 rpm 相关

    “ ” 允许通过$符引用其他变量

    1.1.1.1 2.2.2.2 3.3.3.3

    2.4.1 查询某个软件包是否安装

    [[email protected] ~]# rpm -qa tree

    tree-1.5.3-3.el6.x86_64

    ‘’禁止引用其他变量符,视为普通字符

    [[email protected] ~]# echo ${serip[*]}

    2.4.2 查询软件包里面的内容

    [[email protected] ~]# rpm -ql tree

    /usr/bin/tree

    /usr/share/doc/tree-1.5.3

    /usr/share/doc/tree-1.5.3/LICENSE

    /usr/share/doc/tree-1.5.3/README

    /usr/share/man/man1/tree.1.gz

    `` 将命令执行的结果输出给变量

    1.1.1.1 2.2.2.2 3.3.3.3

    2.4.3 查询某个命令属于哪个软件包

    查询的时候要使用绝对路径

    [[email protected] ~]# rpm -qf `which crond` 

    cronie-1.4.4-16.el6_8.2.x86_64

     

    第1章 练习题 1.1 每天晚上 12 点,打包站点目录 /var/www/html 备份到 /data 目录下(最好每次备份按时间生成不同的备份包) 1.1....

    [[email protected] ~]# echo "$PWD is lujing"

    ----------

    /root is lujing

    统计数组元素的个数

    [[email protected] ~]# echo '$PWD is lujing'

    [[email protected] ~]# echo ${#serip[*]}

    $PWD is lujing

    3

    [[email protected] ~]# echo $a

    --------

    1000

    统计模个元素值的长度 第一个代表0 第二个代表1 1.1.1.1 是7位.也算)

    [[email protected] ~]# echo $aaaaaaaa  //系统把$aaaaa视为一个变量

    [[email protected] ~]# echo ${#serip[0]}

     

    7

    [[email protected] ~]# echo ${a}aaaaaa   //把变量用{}括起来,系统才会去输出变量

    ---------

    1000aaaaaa

    输出模个位置的元素 从所有的数组里选取第2个元素

    #echo `ls`  反引号中的命令时可以单独执行的,然后再由echo输出

    [[email protected] ~]# echo ${serip[@]:2}

     

    3.3.3.3

    扩展:” “反斜杠,作用屏蔽字符的特殊意义

    ------

    test命令

    [[email protected] ~]# hostname=(www.baidu.com www.sina.com www.uplooking.com)

     用途:测试表达式是否成立,成立返回值为0,否返回值为其他值。

    [[email protected] ~]# echo ${hostname[2]}

     格式:test  条件表达式  [条件表达式]

    www.uplooking.com

     

    [[email protected] ~]# echo ${hostname[2]:0}

     ≡ 常见的测试类型

    www.uplooking.com

          测试文件的状态

    [[email protected] ~]# echo ${hostname[2]:4}

          字符的串比较

    uplooking.com

          整数值比较

    [[email protected] ~]# echo ${hostname[2]:4:9} 从第几个开始输出 输出几位

          逻辑测试

    uplooking

     

    --------

    测试文件的状态

    把从屏幕输入的三次IP 地址 存放到数组serip里

       格式:[操作符   文件或目录]

    把数组色日跑得三个元素值输出到屏幕上

      常见的测试操作符

    1 #!/bin/bash

    -d :测试是否为目录【directory】

    2 read -p "请输入第一个IP地址" a[0]

     

    3 read -p "请输入第二个IP地址" a[1]

    [[email protected] /]# [ -d /var/spool/ ]

    4 read -p "请输入第三个IP地址" a[2]

    [[email protected] /]# echo $?

    5

    0

    6 echo ${a[@]}

     

    用循环的方式给数组赋值

    -e:测测试目录或文件是否存在【exist】

    1 #!/bin/bash

     

    2 read -p "清输入监控主机的台数:" a

    [[email protected] /]# [ -e /etc/passwd ]

    3 i=0

    [[email protected] /]# echo $?

    4 while [ $i -lt $a ]

    0

    5 do

     

    6 read -p "清输入第一台主机ip:" serip[$i]

    -f:测试是否为文件【file】

    7 let i

     

    8 done

    [[email protected] Packages]# [ -f /etc/passwd ]

    9

    [[email protected] Packages]# echo $?

    10

    0

    11 echo ${serip[@]}

    [[email protected] Packages]#

    用循环的方式输出数组元素

     

    1 #!/bin/bash

    -r:测试当前的用户是否有读取的权限【read】

    2 read -p "清输入监控主机的台数:" a

     

    3 i=0

    [[email protected] /]# [ -r /etc/shadow ]

    4 while [ $i -lt $a ]

    [[email protected] /]# echo $?

    5 do

    0

    6 read -p "清输入第一台主机ip:" serip[$i]

    [[email protected] /]#

    7 let i

     

    8 done

    -w:测试当前的用户是否有写的权限【write】

    9 echo "-------------------------------------------"

     

    10 for i in `echo ${serip[@]}`

    [[email protected] /]# [ -w /etc/shadow ]

    11 do

    [[email protected] /]# echo $?

    12 echo $i

    0

    13 done

    [[email protected] /]#

    14 echo "----------------------------------------"

     

    15 for ((i=0;i<$a;i ))

    -x:测试当前的用户是否可执行和该文件【excute】

    16 do

     

    17 echo ${serip[$i]}

    [[email protected] /]# [ -x /etc/shadow ]

    18 done

    [[email protected] /]# echo $?

    -----------------------------------------------------------------------

    1

    -----------------------------------------------------------------------

    [[email protected] /]# ll /etc/shadow

    正则表达式

    ----------. 1 root root 1086 2月  26 22:38 /etc/shadow

    正则 是用符号来描述有相同属性的数据

     

    转意 在普通情况下 是把特殊符号变成普通符号

    -L:测试是否为符号链接文件【link】

    在grep 正则表达式中) 是把普通符号变成特殊符号 直接写是没有特殊意义的

     

    grep [选项]‘正则表达式’ 文件名

     

    命令| grep [选项]‘正则表达式’ 文件名

    [[email protected] /]# ll /etc/shadow

    处理方式

    ----------. 1 root root 1086 2月  26 22:38 /etc/shadow

    逐行处理 把与正则表达式匹配的行输出 以行为处理单位

    [[email protected] /]# [ -L /etc/shadow ]

    -------------------

    [[email protected] /]# echo $?

    正则符号

    1

    ^ 开头

    整数值比较

    $ 结尾

     格式:[ 整数1 操作符整数2 ]

    ^a 以a为开头

    常用的操作测试符

    ^ 以 为开头的

      -eq:等于(Equal)

    ^# 以#开头的

      -ne:不等于(Not Equal)

    $ 结尾

      -gt:大于(Greater Than)

    ^$ 有开头和结尾

      -lt:小于(Lesser Than)

    a$ 以a为结尾的

      -le:小于或等于(Lessser or Equal)

    ^ab$ 以a开头 b为结尾的

      -ge:大于或等于(Greater or Equal)

    . 匹配任意单个字符任意一位)

    案例

    .$ 配置以点结尾的行

      如果登录用户数小于或等于10则输出YES

    * 前面的字符出现0此或者无穷次

     

    * >=o o个到多个

    [[email protected] 桌面]# who|wc -l

    + >= 1 1 个到多个

    2

    ? 是0次或1

    [[email protected] 桌面]# [ `who|wc -l` -le 10 ] && echo "YES"

    ***************************************************

    YES

    用grep 的时候 下面的这几个必须要转意

     

    ^ $ . [] * ? { } < >/ | ( )

    变量的加减法运算:

    ****************************************************

    变量的加法运算:

    ) 保存 匹配的模式

    [[email protected] ~]# a=1000

    ab) 一个整体

    [[email protected] ~]# echo $a

    ^pac*j$ c出现0此或者无穷次

    1000

    ^pac)*j$ *前面的ac出现0此或者无穷次

    [[email protected] ~]# expr $a $a

    [ ] 匹配范围内的也就是任意一个

    2000

    [afb] 包括 afb里任意一个都匹配

    [[email protected] ~]# echo $a $a              //这是2中错误的操作,运算必须使用expr

    [a-d]只要里面的有任意一个都匹配

    1000 1000

    [a-Z]所有的字母

    [[email protected] ~]# expr $a $a                //$a $a 要有空格否则也是错误的

    .* 表示所有字符

    1000 1000

    [^a-c] ^在[]表示取反 没有a到c的都匹配

    变量的乘法运算:

    ^[a-c] 以abc开头的

    [[email protected] ~]# expr $a * $a              //* 在操作系统中视为特殊字符,屏蔽字符的特殊意义

    ^[^a-c] 不以abc开头的行

    expr: syntax error

    | 或

    [[email protected] ~]# expr $a * $a

    (abc|def)* abc出现o到无穷此 或者 def出现0次或者无穷

    1000000

    w(abc|def)x 表示wabcx 或者是wbefx 都匹配

    [[email protected] ~]# expr 2 / 1      //除法

    匹配次数

    2

    { }指定前面的表达式出现的次数

    [[email protected] ~]# expr 2 – 1        //减法

    goo){1}d =good

    1

    goo){2}d =gooood 俩个oo 出现2次

    [[email protected] ~]# expr 2 % 1                //取余

    {2,} >=2

    0

    {2,4} >=2 and <=4 最小出现2次最大出现4次

    位置变量:

    < <shc 匹配行里以shc为首的单词

    0-9           常用的为1-9

    >/ a>/ 匹配行里以a为结尾的

    通过脚本来看些位置变量:

    正则选项

    [[email protected] shellscripts]# cat a.sh

    -v 取反

    #!/bin/bash

    -i 不分大小写

    echo $1

    -n 显示匹配文件的行号

    echo $2

    -c 显示正则表达式匹配的行数

    echo $3

    -q 不显示输出的信息

    echo $0

    去掉前面有空格 和#的 只要有效行

    [[email protected] shellscripts]# a.sh a b c d e

    [[email protected] opt]# grep -v "^$|^#" /etc/httpd/conf/httpd.conf

    a

    面试的时候肯能出现的匹配

    b

    匹配出make地址HWADDR

    c

    [[email protected] opt]# grep "([0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}" /etc/sysconfig/network-scripts/ifcfg-eth0

    /shellscripts/a.sh           //$0打印的是脚本笨的名字

    HWADDR=54:E6:FC:71:17:45

     

    ip地址

    [[email protected] shellscripts]# a.sh 1 2

    域名 www . baidu . com

    3

    [[email protected] opt]# grep "[a-z0-9]{1,}.[a-z0-9]{1,}.[a-z]{2,3}" ifcfg-eth0 aaawww.baidu.com

    [[email protected] shellscripts]# a.sh 2 3

    主机名

    5

    url 地址 论坛上贴网址的

    [[email protected] shellscripts]# cat a.sh

    邮箱

    #!/bin/bash

    ---------------------------------------------------

    echo `expr $1 $2`             //$1和$2代表了2个位置变量

    sed 交换式的流编辑器

    [[email protected] shellscripts]#

    打印 删除 替换 复制 剪切 粘贴 导入 导出

     

    处理的时候以行为单位 对文件进行逐行处理

    预定义变量

    用法

    $#  : 命令行中位置参数的个数

    sed [ 选项] “动作” 文件名字

    $*  : 所有位置参数的内容

    命令 | sed [ 选项] “动作” 文件名字

    $?  : 上一条命令执行后返回的状态,当状态为0时表示正常,非0表示执行异常或出错。

    打印 “p”

    $$  : 当前所在进程的进程号

    会显示两行 一个是原数据 一个是处理完以后的数据

    $!  :  后台运行的最后一个进程号

    sed "p" /etc/passwd 有两行

    $0  :  当前执行的进程/进程名

    sed "p;p" /etc/passwd 多次动作用;间隔

    脚本的规范书写:

    sed "p;=" /etc/passwd = 显示行号

    #!/bin/bash

    root:x:0:0:root:/root:/bin/bash p打印的内容

    #Date : 2014-5-28

    1 =显示的内容

    #Author : Create by meng       //脚本的创始人

    root:x:0:0:root:/root:/bin/bash 原数据

    #Mail :~~                                   //邮件地址

    bin:x:1:1:bin:/bin:/sbin/nologin

    #Func (do):this is useradd user script.            //脚本的作用

    2

    #V1.1                  //脚本的版本

    bin:x:1:1:bin:/bin:/sbin/nologin

    echo "hello,world!"            //后面的才是脚本的内容

    -n 不显示原数据 只显示输出后的结果

     

    [[email protected] opt]# sed -n "p" /etc/passwd

    文章版权:

    打印模几行

     

    [[email protected] opt]# sed -n "2,5p" /etc/passwd

    字符串比较

    [[email protected] opt]# sed -n "1p;3p;5p" /etc/passwd

     格式 [ 字符串1 = 字符串2 ]

    ---------------------

          [ 字符串1 != 字符串2 ]

    删除 d

          [ -z 字符串 ]

    只删除第一行的显示内容

     

    [[email protected] opt]# sed "1d" /etc/passwd

    常用的测试操作符

    [[email protected] opt]# sed "1d;3d" /etc/passwd

      =:字符串内容相同

    起始行 结果行

     !=:字符串内容不相同,!号表示相反的意思

    [[email protected] opt]# sed "1,3d" /etc/passwd

      -z:字符内容为空

    加 -i 选项 是操作原文件慎用)

    #read -p "input your name: "  name

    [[email protected] opt]# sed -i "1d" /etc/passwd

    root

    ------------------------------

    #echo $name

    用正则表达式来删除 必须要用 / / d 格式匹配

    #[ $name != "root"] && echo "name is erro"

    [[email protected] opt]# sed -n "/xly/,/abc/d" /etc/passwd

    ##read -p "input your name: "  name

    从第 2行开始包括第2行)在往下删去2行

    zhangsan

    [[email protected] ~]# sed "2, 2d" /etc/passwd

    #[ $name != "root"] && echo "name is erro"

    从2开始 删掉第一个是5的倍数行之间的行

    #echo $name

    [[email protected] ~]# sed "2,~5d" /etc/passwd

    文章版权:

    删除偶数行能除2的) 每2行删去第1行

     

    [[email protected] ~]# sed "1~2d" /etc/passwd

    逻辑测试

    --------------------------------

       格式:[表达式1]   操作符  [表达式2]

    替换 s “ s / / /gi“ g全局 i忽略大小写

      常用的测试操作符

    [[email protected] ~]# sed -n "s/a/b/gi" /etc/passwd

       -a 或&&:逻辑与,“而且”的意思

    替换多个范围的 1行到3行

      #前后两个表达式都成立是整个测试结果才为真,否则为假

    [[email protected] ~]# sed -n "1,3s/a/b/gi" /etc/passwd

       (前面真则执行后面)

    ------

       -o或||:逻辑或,或者的意思

    用正则 修改 用// 圈起来

       #操作符两边至少一个为真时,结果为真,否则结果为假

    把所有的数字改成字母

        (前面假则执行后面)

    [[email protected] ~]# sed -n "s/[0-9]/b/g" /etc/passwd

       !:逻辑否

    把包含有字母都删除

      #当指定条件不成立时,返回结果为真

    [[email protected] ~]# sed -n "s/[a-z]//g" /etc/passwd

     

    修改运行级别到3

         if条件语句   --单分支

    [[email protected] ~]# grep initdefault /etc/inittab

    当“条件成立“时执行相应的操作

    # 0 - halt (Do NOT set initdefault to this)

             if  条件测试命令               if 磁盘已用空间>80%

    # 6 - reboot (Do NOT set initdefault to this)

                     then 命令序列   ==》      then 报警

    id:5:initdefault:

               fi             

    [[email protected] ~]# sed "/id/s/[0-6]/3/" /etc/inittab

    应用案例:

    #

      如果/boot分区的空间使用超过80%,输出报警信息

    在sed 的正则表达式里

      #!/bin/bash

    -r

     RATE=`df |awk'NR==4{print int($5)}'`

    在正则表达式里 不用转意符 可以用-r 解决

     if [$RATE -gt 80]

    [[email protected] ~]# sed -r "/id/s/[0-6]{2}/3/" /etc/inittab

      then

    把/etc/passwd 文件里 没一行的第一个字符删掉

      echo "warning,DISK is full!"

    [[email protected] ~]# sed -n "s/.//" /etc/passwd

      if

    把/etc/passwd 文件里 每一行的第一个和最后一个字符删掉

     

    ) 保存所匹配的字符 & 代替你查找的所有字符

     

    每一个模式 是1 2 ...9 每个模式对应前面的第几个)里的内容

                     if条件语句--双分支

    出现在第一个 是开头 第二个是去掉最后一个的所有内容 的三个是最后一个内容

    当“条件成立”、“条件不成立”时执行不同的操作

    [[email protected] ~]# sed -n -r "s/(.)(.*)(.)/2/" /etc/passwd

     

    修改ip最后的地址为254

    if 条件测试命令                if 3306端口是否在监听状态

    [[email protected] opt]# sed -r "s/(192.168.1.)(.*)/1254/" ip.txt

     then 命令序列1         ==》      then mysqld 服务已运行

    192.168.1.254

     else 命令序列2                    else 启动mysqld服务

    192.168.1.254

    fi                   

    192.168.1.254

     

    192.168.1.254

    引用案例:

    192.168.1.254

    判断vsftp是否在运行。若已运行则输出提示信息,否则重新启动vsftp服务

    192.168.1.254

    #!/bin/bash

    192.168.1.254

    service vsftp status &>/dev/null

    把一个文件所有的大写 字母加上个小括号

     if [ $? -eq 0 ]

    [[email protected] opt]# sed "s/[A-Z]/(&)/g" /etc/passwd

    then

    -----------------------

     echo "vsftp service is running"

    添加 a 默认的是每一行都添加一个

     else

    [[email protected] opt]# sed -r "aGATEWAY=192.168.1.254" ifcfg-eth0

      /etc/init.d/vsftp restart

    指定位置添加

     fi

    [[email protected] opt]# sed -r "1aGATEWAY=192.168.1.254" ifcfg-eth0

     

    插入 i 插入到上面

    如果/boot分区的空间使用超过80%,输出警报信息。我们来写个脚本

    [[email protected] opt]# sed -r "1iGATEWAY=192.168.1.254" ifcfg-eth0

     

    替换 c

    #vi a.sh

    第一行替换成GATEWAY....

    #!/bin/bash

    [[email protected] opt]# sed -r "1cGATEWAY=192.168.1.254" ifcfg-eth0

    #a.sh

    导入 r

    NUM=`df | awk 'NR==5{print int($5)}'`

    把有a里的内容 导入到搜索出来1这行的内容的下面

    if

    把只要有1的行导入到a.txt里去

    [ $NUM -gt 80 ]

    什么内容到导入到那里原文件

    then

    [[email protected] opt]# sed -r "/1/r a.txt" 1.txt

     echo "Warning,DISK is full!"

    导出 w

    if

    把有a的内容写到 1.txt里去 会覆盖之前的内容

     

    把只要有a的导出到1.txt里

    awk的额外扩展

    [[email protected] opt]# sed -r "/a /w 1.txt" a.txt

     

    ------------

    [[email protected] ~]# cat /etc/passwd | grep bash | awk -F: '{print ($1)}'

    命令组

    root

    [email protected] opt]# sed -n "2=;2p" a.txt

    lenovo

    [[email protected] opt]# sed -n "2{=;p}" a.txt

    [[email protected] ~]# ^C

    -e 如果有多个命令要执行的时候 可以加多个 -e 连起来 作成一个命令组

    文章版权:

    [[email protected] opt]# sed -n -e "2=" -e "2p" a.txt、

     

    除了第一行剩下的内容 取反

    for循环语句                            for  收件人  in 邮件地址列表

    [[email protected] opt]# sed -n "1 ! p" 2.txt

    根据变量的不通值,重复执行一组命令操作   ==》                do

    -------------------------

    for 变量名  in 取值列表                       发邮件    

    删出 d

    do                                        done

    [[email protected] opt]# sed "d" a.txt

    命令序列

    4n 把当前行 读出下一行 也就是 第4行不读 其他的 都读

    done

    [[email protected] opt]# sed "4n;d" a.txt

     

    -----------------

    #!/bin/bash

    sed 复制

    for TM in a b c d e

    有俩个空间 sed的缓存

    do

    一个是模式空间 里面不存数据

    echo $TM

    当sed 处理一个流的时候 他会把他放到 里买 处理的时候拿进来 处理完了拿出去

    sleep 1

    二个是保持空间

    done

    默认情况下什么都没有 只有一个换行符n

    ~                                                                                                                                                                 

    俩个选项

    重复测试指定的条件,只要条件成立则反复执行对应的命令操作

    剪贴

     

    H 追加导入到保持空间

    while 命令或表达式          while 可用内存<100mb

    h 覆盖导入到保持空间

    do             ==》do

    [[email protected] opt]# sed "1h;1d;5G" 2.txt

         命令列表      获取可用内存数

    粘贴

    done                    done

    G 追加粘贴到模式空间

    文章版权:

    g 覆盖粘贴到模式空间

     

    [[email protected] opt]# sed "1H;5G" 2.txt

    多重分支语句

    [[email protected] opt]# sed "1,3h;5G" 2.txt

    [email protected] ~]# cat a.sh

    -------------------------------------

    #!/bin/bash

    awk 单独的一门语言 也是逐行处理

    #a.sh

    awk 的格式

    case $1 in

    awk [选项] “动作” 文件名

    start)

    命令 | awk [选项] “动作” 文件名

          echo "start...."

    awk -F":" '{print FILENAME}'

               ;;

    位置变量 第一列的值就是$1

    stop)

    $1 。。。$n 分割

          echo "stop......"

    $0 代表整个行的信息

          ;;

    位置变量

    restart)

    [[email protected] opt]# awk -F":" '{print $1,$2}' /etc/passwd

          echo "restart........"

    [[email protected] opt]# head /etc/passwd | awk -F":" '{print $1,$2}'

          ;;

    打印当前文件名 FILENAME

    laod)

    [[email protected] opt]# awk -F":" '{print FILENAME}' /etc/passwd

         echo "laod......."

    打印分割类的个数 NF

          ;;

    [[email protected] opt]# awk -F":" '{print NF}' /etc/passwd

    status)

    当前处理行的行数 NR

          echo "start....."

    [[email protected] opt]# awk -F":" '{print NR}' /etc/passwd

          echo "stop......"

    处理当前行在文件内的行数FNR

          ;;

    [[email protected] opt]# awk -F":" '{print FNR}' /etc/passwd

    esac

    AWK的默认分隔符 为空格 和 tab键默认时可以省略 -F

     

    [[email protected] opt]# head -3 /etc/passwd | awk -F":" '{print $1,$3,$4}'

    [[email protected] ~]# ./a.sh start

    root 0 0

    start....

    bin 1 1

    [[email protected] ~]# ./a.sh stop

    daemon 2 2

    stop......

    -------------

    [[email protected] ~]#

    awk 处理数据的时候顺序是三个 行前 行中 行后

    [[email protected] ~]# cat a.sh

    行前

    #!/bin/bash

    BEGIN{}

    #a.sh

    [[email protected] opt]# awk -F":" 'BEGIN{print NR}' /etc/passwd

    read -p "input:" NUM

    0

    case "$NUM" in

    行中

    [a-z]|[A-Z])

    {}

          echo "it is english"

    [[email protected] opt]# awk -F":" '{print NR}' /etc/passwd

          ;;

    行后的

    [0-9])

    END{}

          echo "it is shuzi"

    [[email protected] opt]# awk -F":" 'END{print NR}' /etc/passwd

          ;;

    73

    *)

    -------------------

          echo "........."

    用正则

          ;;

    awk '条件{print NR}'

    esac

    ~ 匹配

    [[email protected] ~]#

    !~ 不匹配

     

    匹配是root的

    [[email protected] ~]# ./a.sh

    [[email protected] opt]# awk -F ":" '$1~/root/{print $1}' /etc/passwd

    input:2

    root

    it is shuzi

    比较符号

    [[email protected] ~]# ./a.sh

    = == != > >= < <=

    input:a

    逻辑比较 || &&

    it is english

    运算符号

    [[email protected] ~]# ./a.sh @

    + - * / % += -= *= /=

    input:@

    i=5

    .........

    i =2

    [[email protected] ~]# ./a.sh

    i=i+2

    input:#

    i=7

    .........

    ---------------------

    [[email protected] ~]#

    awk流程控制

     

    流程控制

          shift迁移语句

    分支结构

    用于迁移位置变量,将$1~$9依次向左传递

    if (条件) 动作

     

    若有多个动作,则要用大括号将动作体包含起来

    [[email protected] ~]# ./a.sh 10 20

    if (条件) {动作 1;动作 2}

    The sum is: 30

    # awk -F : '{if ($1 == "root") print $1}' /etc/passwd

    [[email protected] ~]# cat a.sh

    # awk -F: '{if ($1 == "root") {print $1;print $6} }' /etc/passwd

    #!/bin/bash

    if (条件 1)

    #a.sh

    动作 1

    Result=0

    else

    while [ $# -gt 0 ]

    动作 2

          do

    # awk -F: '{if ($1 == "root"){print $1}else print $6}' /etc/passwd

    Result=`expr $Result $1`

    # awk -F: '{if ($1 == "root") print $1;else print $6}' /etc/passwd

          shift

    上面两个命令是等价的 ,要么用分号隔开 ,表示第一个动作体的结束 ,要么将动作体用大括号定位范围

          done

    if (条件 1)

          echo "The sum is: $Result"

    动作 1

    [[email protected] ~]#

    else if(条件 2)

     

    动作 2

     

    else if(条件 3)

    break语句

    动作 3

     

    else

    用于跳出当前的循环体,执行循环体后的语句。

    动作 4

     

    # awk -F: '{if ($1 == "root") print $1;else if ($1 == "seker") print $6;else if ($1 == "zorro") print $7;else print

    函数的应用

    NR}' /etc/passwd

     

    条件 ? 动作 1 : 动作 2

    [[email protected] ~]# ./c.sh

    Expr ? action1 : action2

    46

    # awk -F: '{print ($3<5?$1:$3)}' /etc/passwd

    55

    读前处理和读后处理

    [[email protected] ~]# cat c.sh

    # awk -F: 'BEGIN {print NR,NF}' /etc/passwd

    #!/bin/bash

    00

    #c.sh

    # awk -F: 'END {print NR,NF}' /etc/passwd

    adder(){

    46 7

    echo `expr $1 $2`

    # awk -F: 'BEGIN{i=1} {i } END {print i}' /etc/passwd

    }

    47

     

    练习 找出普通用户的用户名并统计数量

    adder 12 34

    #awk -F: 'BEGIN{i=0} $3>=500 {print $1;i } END {print i}' /etc/passwd

    adder 22 33

    循环语句

    [[email protected] ~]# ./c.sh

    while(条件) {

    46

    动作

    55

    条件运算

    [[email protected] ~]#

    }

     

    # awk -F: '{while($3<3) {print $3,$1;$3 }}' /etc/passwd

     

    BEGIN

    声明:以上知识全来自与自学shell编程总结回顾

    BEGIN 块可以独立使用,不需要引入文件

     

    # awk 'BEGIN{i=1;while(i<100) {print i;i }}'

    文章版权: ...

    练习 打印 100 以内的偶数

    # awk 'BEGIN{i=1;while(i<100) {if (i%2==0) print i;i }}'

    x=1

    do {

    动作 1

    x

    } while (x<5)

    # awk 'BEGIN{i=5;do{print i;i }while(i<10)}'

    # awk 'BEGIN{i=5;do{print i;i }while(i<1)}'

    for(预置;条件;递增) {

    动作

    }

    # awk 'BEGIN {for (x=1;x<=4;x ) print x }'

    输出样式

    # awk -F: '{printf "%-10s %-10d %sn",$1,$3,$7}' /etc/passwd

    %s 字符类型, %d 数值类型

    printf 默认是不输出换行的所以要加n

    10 和 7 是偏移量

    默认是右对齐,所有加个- 就是左对齐,就是把不足的位数用空格填充

    注意:格式与输出列之间要有逗号

    跳转语句

    break 跳出循环

    # awk 'BEGIN {for(x=1;x<5;x ) {if (x==3) break;print x }}'

    1

    2

    continue 在达到循环底部之前终止当前循环 从新开始下一次循环

    # awk 'BEGIN {for(x=1;x<5;x ) {if (x==3) continue;print x }}'

    1

    2

    4

    next 读入下一行 同时返回脚本顶部 这样可以避免对当前行执行其他操作

    # awk -F: 'NR > 5 {next} {print $1} END {print NR}' /etc/passwd

    root

    bin

    daemon

    adm

    lp

    46

    46

    #

    exit 使读取动作终止 并将控制移动到 END,如果没有 END 则终止脚本

    # awk -F: 'NR > 5 {exit} {print $1} END {print NR}' /etc/passwd

    root

    bin

    daemon

    adm

    lp

    6

    [[email protected] pub]# cat -b u.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 news:x:9:13:news:/etc/news:

    [[email protected] pub]# awk -F: 'BEGIN{i=1}NR>5 {next}{print i }END{print NR}' u.txt

    1

    2

    3

    4

    5

    10

    [[email protected] pub]# awk -F: 'BEGIN{i=1}NR>5 {exit}{print i }END{print NR}' u.txt

    1

    2

    3

    4

    5

    6

    [[email protected] pub]#

    数组

    自定义数组

    # awk 'BEGIN {ary[1]="seker";ary[2]="zorro";print ary[1],ary[2]}'

    seker zorro

    # awk 'BEGIN {ary[1]="seker";ary[2]="zorro";for(i in ary) print ary[i]}'

    seker

    zorro

    #

    循环产生数组和取出数组

    # awk 'BEGIN{n=5;for (i=1;i<=n;i ) ary[i]=i 100;for(m in ary) print m,ary[m]}'

    4 104

    5 105

    1 101

    2 102

    3 103

    #

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

    1 root

    2 bin

    3 daemon

    4 adm

    5 lp

    6 sync

    7 shutdown

    8 halt

    9 mail

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

    10 uucp

    11 operator

    12

    12 games

    13 gopher

    14 ftp

    32 rpc

    37 rpm

    本文出自 “history_xcy” 博客,请务必保留此出处

    ...

    本文由新葡亰496net发布于服务器网络,转载请注明出处:新葡亰496net:Linux正则表达式sed,练习题四

    关键词: