shell编程知识点

作者: huxt | 来源:发表于2019-09-25 08:45 被阅读0次

    1.函数

    (1) 函数可以这样定义:

    function fname()

    {

    statements;

    }

    或者

    fname()

    {

    statements;

    }

    甚至是这样(对于简单的函数):

    fname() { statement; }

    (2) 只需使用函数名就可以调用函数:

    $ fname ; #执行函数

    (3) 函数参数可以按位置访问

    $1是第一个参数,$2是第二个参数,以此类推:fname arg1 arg2 ; #传递参数

    2.读取命令返回值(状态)

    命令的返回值被保存在变量$?中。

    cmd;

    echo $?;

    返回值被称为退出状态。它可用于确定命令执行成功与否。如果命令成功退出,那么退出状

    态为0,否则为非0。

    3.比较与测试

    程序中的流程控制是由比较语句和测试语句处理的。Bash能够执行各种测试。我们可以用if、if else以及逻辑运算符来测试,用比较运算符来比较数据项。除此之外,还有一个test命令也可以用于测试

    if-then是条件选择语句,及根据if后面的条件的执行情况在决定程序的执行流程。 

    test可以提高if-then的条件判断能力,test命令中列出的条件如果成立,则test命令就会退出且返回退出状态码0。 

    如果test后面没有任何内容则返回非0,因此可以用来简单判断变量是否为空

    另外一种方法为使用 方括号[ ],比如:

    if [ $value -gt 5 ]

    表示测试变量是否大于5。但是在脚本中用于字符串比较的>必须加上转义字符,否则会被识别为重定向符号。

    对比字符串只能使用==、<、>、!=、-z、-n。对比字符串时,末尾一定要加上x(或者a、b等)一个字符,因为if [ $1x == "ab"x ]时如果没有了x ,并且$1是"",这个语句会翻译成if [  == "ab" ],左边相当于没有东西了,会报语法错误。或者使用[[  ]],就不需要x了。使用<或者>时,如果是用[  ],需要用转义符"\",如\>。

    对比数字使用既能使用-eq、-ne、-gt、-ge、-lt、-le,也能使用==、<、>、!=。其中-eq的意思是equal,-ne是unequal,-gt是greater than,-ge是greater than or equal to,-lt是less than,-le是less than or equal to

    使用正则表达式

       if在对比时可以使用正则表达式,如if [[ $1 == a*a ]](或者if [ $1x == a*ax ])。如果使用""把a*a包围起来,*就会变成字符*,而不是正则表达式中的*。

    [和[[的区别

       区别一。在[中使用逻辑运算符,需要使用-a(and)或者-o(or)。在[[中使用逻辑运算符,需要使用&&或者||。

       区别二。[是shell命令,在它包围的表达式是它的命令行参数,所以串比较符>和<需要转义,否则就变成io重定向了。[[是shell关键字,不会做命令行扩展,所以<和>不需要进行转义。但是语法相对严格,如在[中可以用引号括起操作付,[[则不行。如if [ "-z" "ab" ]。

       区别三。[[可以做算术扩展,[则不行。如if [[ 11+1 -eq 100 ]],而if [ 11+1 -eq 100 ]则会报错。

    文件判断

       在高级语言中,判断文件是否存在等各种状态都是需要调用特定的函数进行判断。而在shell中,这方面就比较方便些,只需要运算符即可。

       常用的文件判断运算符如下:

    -e 文件是否存在

    -f  文件是否是普通文件(不是目录、设备文件、链接文件)

    -s  表示文件大小不为0

    -d 表示文件是否是目录

    -b 表示是块设备(光驱、软盘等)

    -c  表示是字符设备(键盘、声卡等)

    -p 表示是管道

    -h 表示是符号链接

    -S 表示是否是socket

    -r、-w、-x表示文件是否有可读、可写、可执行权限(指运行这个测试命令的用户)

    f1 -nt f2      f1是否比f2新(new than)

    f1 -ot f2      f1是否比f2旧(old than)

    f1 -ef f2      f1和f2是否是相同文件的硬链接

    4.变量

    1.)自动定义变量

    1.定义变量量 :变量量名=变量量值 ,不不允许数字命名, 不不能使⽤用横岗命名

    2.引⽤用变量量 :$变量量名 或 ${变量量名}

    3.查看变量量 :echo $变量量名 set显示所有变量量,包括⾃自定义变量量和环境变量量

    4.取消变量量 :unset 变量量名 作⽤用范围:仅在当前 shell 中有效

    2.)系统环境变量

    1.定义环境变量量 :export export 变量量 ,将⾃自定义变量量转换成环境变量量

    2.引⽤用环境变量量 :$变量量名 或 ${变量量名}

    3.查看环境变量量 :echo $变量量名 env |grep Name

    4.取消环境变量量 :unset 变量量名

    5.变量量作⽤用范围 :在当前shell和⼦子shell有效

    3.)位置参数变量量

    脚本参数传参: $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10}

    4.)预先定义变量量

    $0 脚本⽂文件名

    $* 所有的参数

    $@ 所有的参数

    $# 参数的个数

    $$ 当前进程的 PID

    $! 上⼀一个后台进程的 PID

    $? 上⼀一个命令的返回值 0 表示成功

    5.) 变量量赋值⽅方式

    a.显式赋值(变量量名=变量量值)  a = 3

    b.read 从键盘读⼊入变量量值

    read 变量量名

    read -p "提示信息: " 变量量名

    read -t 5 -p "提示信息: " 变量量名

    read -n 2 变量量名

    注意事项: 定义或引⽤用变量量时注意事项: " " 弱引⽤用 ' ' 强引⽤用

    c.``命令替换等价于 $() 反引号中的 shell 命令会被先执⾏行

    [root@bgx ~]# touch `date +%F`_file1.txt

    [root@bgx ~]# touch $(date +%F)_file2.txt

    [root@bgx ~]# disk_free3="df -Ph |grep '/$' |awk '{print $4}'"

    [root@bgx ~]# disk_free4=$(df -Ph |grep '/$' |awk '{print $4}')

    [root@bgx ~]# disk_free5=`df -Ph |grep '/$' |awk '{print $4}'`

    5.变量量数值运算

    1.整数运算 expr + - \* / %

    expr 1 + 2

    expr $num1 + $num2

    2.整数运算 $(()) + - * / %

    echo $(($num1+$num2))

    echo $((num1+num2))

    echo $((5-3*2))

    echo $(((5-3)*2))

    echo $((2**3))

    sum=$((1+2)); echo $sum

    3.整数运算 $[] + - * / %

    echo $[5+2]

    echo $[5**2]

    4.整数运算 let + - * / %

    let sum=2+3;

    echo $sum

    5.⼩小数运算 bc + - * / %

    echo "2*4" |bc

    echo "2^4" |bc

    echo "scale=2;6/4" |bc

    awk 'BEGIN{print 1/2}'

    echo "print 5.0/2" |python

    6.变量量删除替换

    1.从前往后删除变量量内容

    url=www.sina.com.cn

    //获取变量量值的⻓长度

    [root@bgx ~]# echo ${#url}

    //输出变量url

    [root@bgx ~]# echo ${url}

    //从前往后,最短匹配

    [root@bgx ~]# echo ${url#*.}

    //从前往后,最⻓长匹配(贪婪匹配)

    [root@bgx ~]# echo ${url##*.}

    2.从后往前删除变量量内容

    //从后往前,最短匹配

    [root@bgx ~]# echo ${url%.*}

    //从后往前,最⻓长匹配 贪婪匹配

    [root@bgx ~]# echo ${url%%.*}

    [root@bgx ~]# echo ${url#a.}

    [root@bgx ~]# echo ${url#*sina.}

    3.索引及切⽚片

    [root@bgx ~]# echo ${url:0:5}

    [root@bgx ~]# echo ${url:5:5}

    [root@bgx ~]# echo ${url:5}

    4.变量量内容替换

    [root@bgx ~]# url=www.sina.com.cn

    [root@bgx ~]# echo ${url/sina/baidu}

    [root@bgx ~]# url=www.sina.com.cn

    [root@bgx ~]# echo ${url/n/N}

    //贪婪匹配

    [root@bgx ~]# echo ${url//n/N}

    5.变量量替代

    ${变量量名-新的变量量值}

    变量量没有被赋值:会使⽤用“新的变量量值“ 替代

    变量量有被赋值(包括空值): 不不会被替代

    //例例1

    取消url变量

    [root@Shell day01]# unset url

    [root@Shell day01]# echo $url

    6.变量量替代(同5)

    ${变量量名:-新的变量量值}

    变量量没有被赋值(包括空值): 都会使⽤用“新的变量量值“ 替代

    变量量有被赋值: 不不会被替代

    7.变量量⾃自增

    [root@bgx ~]# unset i

    [root@bgx ~]# unset j

    [root@bgx ~]# i=1

    [root@bgx ~]# j=1

    [root@bgx ~]# let x=i++ 先赋值,再运算

    [root@bgx ~]# let y=++j 先运算,再赋值

    //对变量量值不不会产⽣生任何影响

    [root@bgx ~]# echo $i

    2

    [root@bgx ~]# echo $j

    2

    //对表达式的值的影响

    [root@bgx ~]# echo $x

    1

    [root@bgx ~]# echo $y

    2

    对变量量的值的影响:

    [root@bgx ~]# i=1

    [root@bgx ~]# let i++

    [root@bgx ~]# echo $i 2

    案例:

    8.⽂文件测试

    https://www.cnblogs.com/fulucky/p/8027024.html

    [ -e dir|file ]

    [ -d dir ] 是否存在,⽽而且是⽬目录

    [ -f file ] 是否存在,⽽而且是⽂文件

    [ -r file ] 读权限

    [ -x file ] 执⾏行行权限

    [ -w file ] 写权限

    1.常⻅见使⽤用⽅方式

    [ ! -d /bbb ] && mkdir /test

    [ -d /bbb ] || mkdir /test

    2.脚本使⽤用⽅方式

    2.数值⽐比较

    数值⽐比较 [ 整数 1 操作符 整数 2 ]

    [ 1 -gt 10 ] ⼤大于

    [ 1 -lt 10 ] ⼩小于

    [ 1 -eq 10 ] 等于

    [ 1 -ne 10 ] 不不等于

    [ 1 -ge 10 ] ⼤大于等于

    [ 1 -le 10 ] ⼩小于等于

    1.条件测试, 脚本使⽤用案例例, 创建⽤用户

    2.查看磁盘/当前使⽤用状态,如果使⽤用率超过80%则报警发邮件

    //怎么看磁盘使⽤用率,怎么获取对应的值

    df -h|grep "/$"|awk '{print $5}'|awk -F '%' '{print $1}'

    /怎么进⾏行行数值⽐比对

    3.查看内存/当前使⽤用状态,如果使⽤用率超过80%则报警发邮件

    Mem_Total=$(free -m|grep "^M"|awk '{print $2}')

    Mem_Use=$(free -m|grep "^M"|awk '{print $3}')

    Mem_B=$((($Mem_Use*100)/$Mem_Total))

    if [ $Mem_B -ge 30 ];then

            echo -e "\033[31m Memory Is Err ${Mem_B}% \033[0m"

        else

            echo -e "\033[32m Memory Is OK ${Mem_B}% \033[0m"

    fi

    3.字符串串⽐比较

    1.字符串串⽐比对

    //⼩小结:变量量为空 或未定义: ⻓长度都为0

    2.多整数⽐比对条件

    3.正则⽐比对

    字符串正则 数字正则

    4.判断⽤用户输⼊入的是否是数字

    5.批量量创建⽤用户脚本, 仅个⼈人使⽤用

    9.流程控制

    1.单分⽀支结构

    2.双分⽀支结构

    3.多分⽀支结构

    3.流程控制语句句case

    4.批量删除⽤用户

    shell中的cat和文件分界符(<<EOF)

    在shell中,文件分界符(通常写成EOF,你也可以写成FOE或者其他任何字符串)紧跟在<<符号后,意思是分界符后的内容将被当做标准输入传给<<前面的命令,直到再次在独立的一行遇到这个文件分界符(EOF或者其他任何字符,注意是独立一行,EOF前面不能有空格)。通常这个命令是cat,用来实现一些多行的屏幕输入或者创建一些临时文件。

    把输出追加到文件

    root@ribbonchen-laptop:~#  cat<<EOF>out.txt

    脚本实现了一个简单的菜单功能:

    脚本编程 脚本呢运行界面

    批量打包:

    使用格式基本是这样的:

    命令 << EOF

        内容段

    EOF

    将“内容段”整个作为命令的输入。

    你的代码里就是用cat命令读入整段字符串并赋值给list变量。

    Here document

    Here Document 是在Linux Shell 中的一种特殊的重定向方式,它的基本的形式如下:

    cmd << delimiter 

        Here Document Content

    delimiter

    它的作用就是将两个 delimiter 之间的内容(Here Document Content 部分) 传递给cmd 作为输入参数

    这里要注意几点

    1.EOF 只是一个标识而已,可以替换成任意的合法字符

    2.作为结尾的delimiter一定要顶格写,前面不能有任何字符

    3.作为结尾的delimiter后面也不能有任何的字符(包括空格)

    4.作为起始的delimiter前后的空格会被省略掉

    5.Here Document 不仅可以在终端上使用,在shell 文件中也可以使用,例如下面的here.sh 文件

    5.expect 定义变量量实现交互⽅方式

    6.expect 进⾏行行参数传递,执⾏行行命令或其他操作

    7.批量量获取在线主机, 进⾏行行秘钥批量量分发

    10.循环控制

    1.for 循环基础语法

    2.for 案例例, 批量量探测主机存活状态

    3.for 循环批量量创建⽤用户

    5.for 循环通过⽂文件批量量创建⽤用户

    6.批量量修改密码

    2.While循环语句句

    3.Shell内置命令

    exit 退出整个程序

    break 结束当前循环,或跳出本层循环

    continue 忽略略本次循环剩余的代码,直接进⾏行行下⼀一次循环

    11.Shell函数应⽤用

    1.定义函数:

    //⽅方式⼀一

    函数名() {

    函数要实现的功能代码

    }

    //⽅方式⼆二

    function 函数名 {

    函数要实现的功能代码

    }

    2.调用函数和函数传参:

    //调⽤用函数

    function_name 即可调⽤用函数

    //函数传参

    fun $1 传⼊入脚本后第⼀一个参数

    fun $* 接收所有参数的传递

    3.函数返回

    4.位置参数

    5.数组传参

    12.数组

    1.定义数组:

    //⼀一次赋多个值,数组名=(多个变量量值)

    [root@Shell ~]# array2=(tom jack alice)

    [root@Shell ~]# array3=(tom jack alice "bash shell")

    [root@Shell ~]# array4=(1 2 3 "linux shell" [20]=puppet)

    //针对每个索引进⾏行行赋值

    [root@Shell ~]# array1[0]=pear

    [root@Shell ~]# array1[1]=apple

    [root@Shell ~]# array1[2]=orange

    [root@Shell ~]# array1[3]=peach

    2.访问数组

    //统计数组元数的个数

    [root@Shell ~]# echo ${#array1[@]}

    4

    //访问数组中的第⼀一个元素

    [root@Shell ~]# echo ${array1[0]}

    pear

    //从数组索引1开始

    [root@Shell ~]# echo ${array1[@]:1}

    apple orange peach

    //从数组索引1开始,访问两个元素

    [root@Shell ~]# echo ${array1[@]:1:2}

    apple orange

    //访问数组中所有数据,相当于echo ${array1[*]}

    [root@Shell ~]# echo ${array1[@]}

    pear apple orange peach

    3.获取数组索引

    [root@Shell ~]# echo ${!array1[@]}

    0 1 2 3

    2.关联数组

    1.定义关联数组, 申明是关联数据

    [root@Shell ~]# declare -A tt_array_1

    [root@Shell ~]# declare -A tt_array_2

    2.给关联数组进⾏行行赋值

    数组名[索引]=变量量值

    [root@Shell ~]# tt_array1[index1]=pear

    [root@Shell ~]# tt_array1[index2]=apple

    [root@Shell ~]# tt_array1[index3]=orange

    [root@Shell ~]# tt_array1[index4]=peach

    //给关联数组⼀一次赋多个值

    [root@Shell ~]# tt_array2=([index1]=tom [index2]=jack [index3]=alice [index4]='bash

    shell')

    3.查看关联数组

    [root@Shell ~]# declare -A

    4.访问数据元数

    //访问数组中的第⼆二个元数

    [root@Shell ~]# echo ${tt_array2[index2]}

    jack

    //访问数组中所有元数 等同于 echo ${array1[*]}

    [root@Shell ~]# echo ${tt_array2[@]}

    bash shell tom jack alice

    //访问数组中所有元数的索引

    [root@Shell ~]# echo ${!tt_array2[@]}

    index4 index1 index2 index3

    3.遍历数组

    1.通过数组元数的个数进⾏行行遍历(不不推荐)

    2.通过数组元数的索引进⾏行行遍历(推荐)

    注意: 将统计的对象作为数组的索引, 仅针对关联数据

    1.数据赋值和遍历

    从/etc/hosts文件中读取文件内容进行赋值

    数组循环

    for 循环遍历数组(hosts是上面赋值的hosts) 运行结果 for 循环读取/etc/hosts中的文件

    统计 /etc/passwd 的 shell 数量量

    统计 Nginx ⽇日志 IP 访问次数

    统计 tcp 的状态信息

    13.正则表达式

    正则匹配

    文件内容:

    //过滤以m开头的行

    [root@Shell ~]# grep "^m" test.txt

    //过滤以m结尾的行

    [root@Shell ~]# grep "m$" test.txt

    //排除空⾏行行, 并打印⾏行行号

    [root@student ~]# grep -vn "^$" xuliangwei.txt

    //匹配任意⼀一个字符,不不包括空⾏行行

    [root@student ~]# grep "." xuliangwei.txt

    //.匹配所有

    [root@student ~]# grep ".*" xuliangwei.txt

    //匹配单个任意字符

    [root@node1 ~]# grep "xuliangw.i" xuliangwei.txt

    //以点结尾的

    [root@student ~]# grep "\.$" xuliangwei.txt

    //精确匹配到

    [root@student ~]# grep -o "8*" xuliangwei.txt

    //匹配有abc的⾏行行

    [root@student ~]# grep "[abc]" xuliangwei.txt

    //匹配数字所在的⾏行行"[^0-9]"

    [root@student ~]# grep "[0-9]" xuliangwei.txt

    //匹配所有⼩小写字⺟母[^a-z]

    [root@student ~]# grep "[a-z]" xuliangwei.txt

    //重复0三次

    [root@student ~]# grep "8\{3\}" xuliangwei.txt

    //重复3个000不不⽤用转义符

    [root@student ~]# grep -E "8{3}" xuliangwei.txt

    //重复数字8, 3-5次

    [root@student ~]# grep -E "8{3,5}" test.txt

    //⾄至少1次或1次以上

    [root@student ~]# grep -E "8{1,}" xuliangwei.txt

    14.sed⽂文本处理

    https://blog.csdn.net/koozxcv/article/details/51455750

    sed是⼀一个流编辑器器, ⾮非交互式的编辑器器,它⼀一次处理理⼀一⾏行行内容.

    处理理时,把当前处理理的⾏行行存储在临时缓冲区中,称为“模式空间”(pattern space)

    接着⽤用 sed 命令处理理缓冲区中的内容,处理理完成后, 把缓冲区的内容送往屏幕。

    接着处理理下⼀一⾏行行,这样不不断重复,直到⽂文件末尾。

    ⽂文件内容并没有改变,除⾮非你 使⽤用重定向存储输出。

    Sed 要⽤用来⾃自动编辑⼀一个或多个⽂文件;简化对⽂文件的反复操作;编写转换程序等

    1.sed命令形式

    sed [options] 'command' file(s)

    2.sed 和正则使用

    与 grep⼀一样,sed 在⽂文件中查找模式时也可以使⽤用正则表达式(RE)和各种元字符。

    正则表达式是括在斜杠间的模式,⽤用于查找和替换,以下是sed⽀支持的元字符。

    使⽤用基本元字符集 , $, ., *, [], [], < >, (), {}

    使⽤用扩展元字符集 ?, +, { }, |, ( )

    使⽤用扩展元字符的⽅方式 + sed -r

    3.sed命令形式

    sed 对指定⾏行行进⾏行行操作,包括打印、删除、修改、追加等。

    sed选项参数

    -e 允许多项编辑

    -n 取消默认的输出

    -i 直接修改对应⽂文件

    -r ⽀支持扩展元字符

    sed 命令参数

    a 在当前⾏行行后添加⼀一⾏行行或多⾏行行

    c 在当前⾏行行进⾏行行替换修改

    d 在当前⾏行行进⾏行行删除操作

    i 在当前⾏行行之前插⼊入⽂文本

    p 打印匹配的⾏行行或指定⾏行行

    n 读⼊入下⼀一输⼊入⾏行行,从下⼀一条命令进⾏行行处理理

    ! 对所选⾏行行以外的所有⾏行行应⽤用命令

    h 把模式空间⾥里里的内容重定向到暂存缓冲区

    H 把模式空间⾥里里的内容追加到暂存缓冲区

    g 取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容

    G 取出暂存缓冲区的内容,将其复制到模式空间,追加在原有内容后⾯面

    多重编辑选项 e:

    //先删除行,然后管道给后⾯面的sed进⾏行行替换,passwd是文件

    [root@Shell ~]# sed '1,9d' passwd | sed 's#root#alex#g'

    //使⽤用-e进⾏行行多次编辑修改操作

    [root@Shell ~]# sed -e '1,9d' -e 's#root#alex#g' passwd

    打印命令 p:

    //打印匹配halt的⾏,/匹配内容/p

    [root@Shell ~]# sed -n '/halt/p' passwd

    //打印第⼆二⾏行行的内容

    [root@Shell ~]# sed -n '2p' passwd

    //打印最后⼀一⾏行行

    [root@Shell ~]# sed -n '$p' passwd

    追加命令 a:

    //给30⾏行行添加配置 \t tab键(需要转义) \n 换⾏行行符

    [root@Shell ~]# sed -i '30a listen 80;' out.txt

    修改命令 c

    //指定某⾏行内容替换

    [root@Shell ~]# sed -i '7c SELINUX=Disabled' /etc/selinux/config

    //正则匹配对应内容, 然后进⾏行行替换

    sed -i '/^SELINUX=/c SELINUX=Disabled' /etc/selinux/config

    //非交互式修改指定的配置⽂文件

    [root@Shell ~]# sed -ri '/UseDNS/cUseDNS no' /etc/ssh/sshd_config

    [root@Shell ~]# sed -ri '/GSSAPIAuthentication/c#GSSAPIAuthentication no' /etc/ssh/

    sshd_config

    [root@Shell ~]# sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config

    文件替换:

    //s表示替换命令,/my/表示匹配my,/Hao Chen’s/表示把匹配替换成Hao Chen’s,/g 表示一行上的替换所有的匹配

    sed "s/my/Hao Chen's/g" pets.txt

    //重定向文件:

    $ sed "s/my/Hao Chen's/g" pets.txt > hao_pets.txt

    //在每一行最前面加点东西:在每行之前加#

    sed 's/^/#/g' pets.txt

    //在每一行最后面加点东西:在每行之后加---

    sed 's/$/ --- /g' pets.txt

    //指定行需要替换的内容:指定第三行

    sed "3s/my/your/g" pets.txt

    //只替换第3到第6行的文本

    sed "3,6s/my/your/g" pets.txt

    //只替换每一行的第一个s:

    sed 's/s/S/1' my.txt

    //只替换每一行的第二个s:

    sed 's/s/S/2' my.txt

    //只替换第一行的第3个以后的s:

    sed 's/s/S/3g' my.txt

    //多次匹配

    第一个模式把第一行到第三行的my替换成your,第二个则把第3行以后的This替换成了That

    sed -e '1,3s/my/your/g' -e '3,$s/This/That/g' my.txt

    删除命令 d

    //指定删除第三⾏行行, 但不不会改变⽂文件内容

    [root@Shell ~]# sed '3d' passwd

    [root@Shell ~]# sed '3{d}' passwd

    //从第三⾏行行删除到最后⼀一⾏行行

    [root@Shell ~]# sed '3,$d' passwd

    //删除最后⼀一⾏行行

    [root@Shell ~]# sed '$d' passwd

    //删除所有的⾏行行

    [root@Shell ~]# sed '1,$d' passwd

    //匹配正则进⾏行行该⾏行行删除,删除mail这一行

    [root@Shell ~]# sed /mail/d passwd

    插⼊入命令 i

    //在文件的某一行上⾯添加内容,30表示行

    [root@Shell ~]# sed -i '30i listen 80;' passwd

    写⽂文件命令 w

    //将匹配到的⾏行行写⼊入到新⽂文件中,newfile是新文件,/root/是匹配字符

    [root@Shell ~]# sed -n '/root/w newfile' passwd

    //将passwd⽂文件的第⼆二⾏行行写⼊入到newfile中

    [root@Shell ~]# sed -n '2w newfile' passwd

    获取下⼀一⾏行行命令 n

    //匹配root的行, 删除root行的下一列

    [root@Shell ~]# sed '/root/{n;d}' passwd

    //替换匹配root⾏行行的下⼀一列列

    [root@Shell ~]# sed '/root/{n; s/bin/test/}' passwd

    暂存和取⽤用命令 h H g G

    //将第⼀一⾏行行的写⼊入到暂存区, 替换最后⼀一⾏行行的内容

    [root@Shell ~]# sed '1h;$g' /etc/hosts

    //将第⼀一⾏行行的写⼊入到暂存区, 在最后⼀一⾏行行调⽤用暂存区的内容

    [root@Shell ~]# sed '1h;$G' /etc/hosts

    //将第⼀一⾏行行的内容删除但保留留⾄至暂存区, 在最后⼀一⾏行行调⽤用暂存区内容追加⾄至于尾部

    [root@Shell ~]# sed -r '1{h;d};$G' /etc/hosts

    //将第⼀一⾏行行的内容写⼊入⾄至暂存区, 从第⼆二⾏行行开始进⾏行行重定向替换

    [root@Shell ~]# sed -r '1h;2,$g' /etc/hosts

    //将第⼀一⾏行行重定向⾄至暂存区, 2-3⾏行行追加⾄至暂存区, 最后追加调⽤用暂存区的内容

    [root@Shell ~]# sed -r '1h; 2,3H; $G' /etc/hosts

    反向选择命令 

    //除了了第三⾏行行,其他全部删除

    [root@Shell ~]# sed -r '3!d' /etc/hosts

    sed匹配替换

    s 替换命令标志

    g ⾏行行内全局替换

    i 忽略略替换⼤大⼩小写

    替换命令 s

    删除⽂文件

    14.Awk⽂文本处理理

    awk 是⼀一种编程语⾔言,⽤用于在 linux/unix 下对⽂文本和数据进⾏行行处理理。

    awk 数据可以来⾃自标准输⼊入、⼀一个或多个⽂文件,或其它命令的输出。

    awk 通常是配合脚本进⾏行行使⽤用, 是⼀一个强⼤大的⽂文本处理理⼯工具。

    awk 的处理理⽂文本和数据的⽅方式如下:

    1.进行逐行扫描⽂文件, 从第一行到最后⼀行

    2.寻找匹配的特定模式的行,在行上进行操作

    3.如果没有指定处理理动作,则把匹配的⾏行行显示到标准输出

    4.如果没有指定模式,则所有被操作的⾏行行都被处理理

    1.awk 的两种形式语法格式

    awk [options] 'commands' filenames

    awk [options] -f awk-script-file filenames

    options

    -F 定义输⼊入字段分隔符,默认的分隔符是空格或tab键

    awk 'BEGIN{print 1/2} {print "ok"} END {print "Game Over"}' /etc/hosts

    2.awk命令格式

    3.Awk ⼯工作原理理

    # awk -F: '{print $1,$3}' /etc/passwd

    1.awk使⽤用⼀一⾏行行作为输⼊入,并将这⼀一⾏行行赋给内部变量量 $0 每⼀一⾏行行也可称为⼀一个记录,以换⾏符结束

    2.awk进⾏行行字段分解,每个字段存储在已编号的变量量中,从 $1 开始

    3.awk默认情况下的分隔符是空格, 是由内部变量量 FS 来确定字段分隔符。初始 FS 为空格

    4.awk打印字段,将以设置的⽅方法使⽤用 print 函数打印

    5.awk在打印的字段间加上空格,因为 $1,$3 之间有⼀一个逗号。逗号它映射为另⼀一个内部变

    量量,称为输出字段分隔符 OFS 默认为空格

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

    4.Awk内部变量量

    1.$0 保存当前记录的内容

    [root@Shell ~]# awk '{print $0}' /etc/passwd

    2.NR 控制输⼊入的总⾏行行数

    //打印整个⽂文本的⾏行行号

    [root@Shell ~]# awk '{print NR,$0}' /etc/passwd

    //打印文件的前三行

    [root@Shell ~]# awk 'NR<=3' /etc/passwd

    3.FNR 记录输⼊文件的编号

    [root@Shell ~]# awk '{print FNR,$0}' /etc/passwd /etc/hosts

    4.NF 保存⾏行行的最后⼀一列列内容

    [root@Shell ~]# awk -F ":" '{print $1,$NF}' /etc/passwd

    5.FS 指定字段分割符,默认空格

    //以冒号作为字段分隔符

    [root@Shell ~]# awk -F: '/root/{print $1, $3}' /etc/passwd

    [root@Shell ~]# awk 'BEGIN{FS=":"} {print $1,$3}' /etc/passwd

    //以空格冒号tab作为字段分割

    [root@Shell ~]# awk -F'[ :\t]' '{print $1,$2,$3}' /etc/passwd

    6.OFS 输出字段分隔符

    //,映射为OFS,初始情况下OFS变量量是空格

    [root@Shell ~]# awk -F: '/root/{print $1,$2,$3,$4}' /etc/passwd

    [root@Shell ~]# awk 'BEGIN{FS=":"; OFS="+++"} /^root/{print $1,$2}' /etc/passwd

    7.RS 输入记录分隔符,默认为换行符,按照空格进行换行

    [root@Shell ~]# awk -F: 'BEGIN{RS=" "} {print $0}' /etc/hosts

    8.ORS 将文件每一行合并为⼀行,以空格为分割

    [root@Shell ~]# awk -F: 'BEGIN{ORS=" "} {print $0}' /etc/hosts

    合并成一行,以空格符间隔

    //通常情况下让输出分隔符为换行符, 然后依次打印响应的字段

    [root@Shell ~]# awk -F ":" 'BEGIN{OFS="\n"}{print $1,$2,$3,$4,$5,$6,$7}' passwd

    //将RS记录值标记为冒号分割, 打印后相当于将每行的内容进行切割

    [root@Shell ~]# awk 'BEGIN{RS=":"}{print $0}' passwd

    8.print 格式化输出函数

    5.Awk模式动作

    awk语句句都由模式和动作组成。

    模式部分决定动作语句句何时触发及触发事件。

    如果省略略模式部分,动作将时刻保持执⾏行行状态。模式可以是条件语句句或复合语句句或正则表达式

    1.正则表达式

    //匹配记录(整⾏行行)

    [root@Shell ~]# awk '/^root/' /etc/passwd

    [root@Shell ~]# awk '$0 ~ /^root/' /etc/passwd

    //匹配字段:匹配操作符(~ !~)

    [root@Shell ~]# awk '!/^root/' /etc/passwd

    [root@Shell ~]# awk '$0 ~ !/^root/' /etc/passwd

    2.比较表达式

    比较表达式采用对⽂文本进行比较,只有当条件为真,才执行指定的动作。

    比较表达式使用关系运算符,用于比较数字与字符串串

    关系运算符

    3.条件表达式

    4.运算表达式

    5.逻辑操作符和复合模式

    //匹配⽤用户名为root并且打印uid⼩小于15的⾏行行

    [root@Shell ~]# awk -F: '$1~/root/ && $3<=15' /etc/passwd

    //匹配⽤用户名为root或uid⼤大于5000

    [root@Shell ~]# awk -F: '$1~/root/ || $3>=5000' /etc/passwd

    6.Awk条件判断

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

    //打印当前管理理员⽤用户名称

    [root@Shell ~]# awk -F: '{ if($3==0){print $1 "is adminisitrator"} }' /etc/passwd

    //统计系统⽤用户数量量

    [root@Shell ~]# awk -F: '{ if($3>0 && $3<1000){i++}} END {print i}' /etc/passwd

    //统计普通⽤用户数量量

    [root@Shell ~]# awk -F: '{ if($3>1000){i++}} END {print i}' /etc/passwd

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

    3.if...else if...else 语句句格式:

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

    7.Awk循环语句句

    1.while循环

    [root@Shell ~]# awk '{i=1; while(i<=NF){print $i; i++}}' b.txt

    2.for循环

    3.awk数组实战

    注意:将需要统计的某个字段作为数组的索引,最后对索引进⾏行行遍历

    1.按索引遍历

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

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

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

    运行结果

    3.⽹网站访问状态统计<当前时实状态ss>

    [root@Shell ~]# ss -an|awk '/:80/{tcp[$2]++} END {for(i in tcp){print i,tcp[i]}}'

    4.统计当前访问的每个IP的数量量<当前时实状态 netstat,ss>

    [root@Shell ~]# ss -an|awk -F ':' '/:80/{ips[$(NF-1)]++} END {for(i in ips){print i,ips[i]}}'

    5.统计当前访问的每个IP的数量量<当前时实状态 netstat,ss>

    [root@Shell ~]# ss -an|awk -F ':' '/:80/{ips[$(NF-1)]++} END {for(i in ips){print i,ips[i]}}'

    相关文章

      网友评论

        本文标题:shell编程知识点

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