shell编程

本文详细介绍了Shell编程的基础,包括变量、条件判断、循环控制以及脚本编写。此外,还深入讲解了 Awk 工具,包括其工作模式、字段处理、模式匹配和条件表达式。通过实例展示了如何使用Awk进行数据处理和分析。最后,提到了一些常用的Shell命令,如echo、test、for和while循环,以及数组和函数的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

shell编程

shell基础

shell简介

  • 什么是shell

    • 命令解释器
    • 编程语言
  • 当前系统shell

    • 支持的shell

      • cat /etc/shells

        • /bin/sh
        • /bin/bash
        • /sbin/nologin
        • /usr/bin/sh
        • /usr/bin/bash
        • /usr/sbin/nologin
    • 使用的shell

      • echo $SHELL
      • cat /etc/passwd
  • 修改当前shell

    • usermod -s /bin/bash root
    • chsh -s /usr/bin/sh root
    • 针对当前用户
  • shell类型

    • 登录shell

      • 以sh结尾的shell
    • 非登录shell

      • /sbin/nologin
      • /bin/false
    • 父shell

      • bash/sh开启子shell
    • 子shell

      • 子shell能继承父shell的环境(命令、位置、变量、资源等)
      • 子shell改变环境不影响父shell
      • 子shell相当于不完全登录
  • 环境变量

    • 配置文件

      • 全局环境配置文件,对所有用户生效

        • /etc/profile
        • /etc/bashrc
      • 用户环境配置文件,只对本用户生效

        • ~/.bash_profile
        • ~/.bashrc
      • 登录加载

        • 完全登录

          • su - user,加载全部4个配置文件
        • 不完全登录

          • su user,只加载2个bashrc
      • 加载顺序

        • /etc/profile > ~/.bash_profile > /etc/bashrc > ~/.bashrc(优先级最高)
    • 查看当前环境变量

      • env
      • export
    • 变量

      • $RANDOM,5位随机数
  • Linux命令

    • 分类

      • 内嵌命令

        • bash自带的命令,不受环境变量影响

        • 查看当前系统内嵌命令:help

        • 帮助手册

          • help 命令
      • 外部命令

        • 由软件包安装的命令,受PATH变量影响
        • 对应的是一个文件,执行命令实际上执行的是该文件
      • 别名命令

        • 查看别名

          • alias
        • 设置别名

          • 临时

            • alias 别名名称=‘动作命令’
          • 永久

            • vim ~/.bashrc

              • alias 别名名称=‘动作命令’
            • vim /etc/bashrc

          • 如:alias hello=‘echo hello world’

        • 取消别名

          • unalias 别名名称
        • 注意

          • 脚本中不能直接使用别名命令,需要先定义
      • 函数

    • 查看类型

      • type 命令

        • type cd

          • cd is a shell builtin

            • 内嵌命令
        • type cat

          • cat is hashed (/usr/bin/cat)

            • 外部命令
        • type cp

          • cp is aliased to `cp -i’

            • 别名
    • 优先级

      • 别名>内嵌命令>外部命令
  • 历史命令

    • 查看

      • history
      • 默认记录1000条,/etc/profile中设置
    • 调用

      • !N
      • N为查询出来的历史命令编号
    • 清除

      • history -c
  • 算数运算

    • 运算符

            • / %(取余,取模) 幂(**/^)
    • 命令

      • echo $[] 或 echo $(())

        • 只能计算整数

          • eg:echo $[100/4]
          • 除法取整,并非四舍五入
        • 幂运算

          • echo $[2**10]
        • 取余/取模

          • 特性:值在0到除数减1之间
          • 应用:获取1-100的随机数–echo $[RANDOM%100+1]
      • bc

        • 交互式,可计算小数。除法默认取整,scale=3设置小数位

        • 非交互式

          • echo -e “scale=3\n10/3” |bc
          • echo “scale=3;10/3” |bc
        • 幂运算

          • echo 2^10 |bc
      • expr

        • expr 1 + 2

          • 运算符两边要有空格,只能计算整数
        • expr 10 + $num

          • 通常用来判断参数是否整数
      • let

        • 通常作变量赋值计算
  • shell脚本

    • 创建脚本

      • 创建脚本文件

        • vim user_add.sh
        • 命名规范:见名知义,.sh结尾
      • 编辑脚本内容

        • #!/bin/bash
          #用于创建用户
          useradd tom #创建tom用户
        • 第一行#!开头指定解释器,便于移植
        • #后面表示注释内容,增加可读性
      • 加上可执行权限

        • chmod +x user_add.sh
    • 执行脚本

      • 方式

        • 脚本路劲执行

          • 用法

            • 脚本路径

            • 示例

              • /root/user_add.sh
              • ~/user_add.sh
          • 特点

            • 需要x权限
            • 调用子shell执行
        • 调用解释器执行

          • 用法

            • 解释器 路径

            • 示例

              • bash user_add.sh
              • sh /root/user_add.sh
          • 特点

            • 不需要x权限
            • 调用子shell执行
        • 点执行

          • 用法

            • . 路径

            • source 路径

            • 示例

              • . user_add.sh
              • source /root/user_add.sh
          • 特点

            • 不需要x权限
            • 在当前shell执行
      • 脚本路径

        • 绝对路径或相对路径都可使用
        • 解释器或点执行时,若在脚本当前目录,路径可直接用脚本名
    • 调试脚本

      • sh -x 脚本路径

shell符号

  • 通配符

    • 用途

      • 一般用于已存在文件的外部操作,如ls,rm,cp,find…
    • 符号

      • :匹配任意长度的任意字符,.txt

      • ?:匹配任意单个字符。f?.txt #f和.txt中间接任意单个字符

      • […]:匹配[ ]内任意单个字符

        • [! ]:!在[ ]内首位表示取反,不匹配[ ]的任意字符
        • [a-Z]:-连接两个字符表示范围,匹配任意单个字母
      • {…}:表示集合

        • {a,z} a和z
        • {a…z} a到z
  • 命令连接符

    • ;

      • 命令连接符,连接多条命令,这些命令依次执行
      • ;:命令结束标识,find中-ok,-exec
    • &&:逻辑与,前面命令执行成功后才会执行后面

    • ||:逻辑或,前后命令只有一条能执行成功

    • !:非,放在命令前面,当正确执行返回错误,当错误执行返回正确

  • 引号

    • “ ”

      • 弱引,引号中可执行变量或$()中命令
    • ’ ’

      • 强引,引号中内容为纯文本,变量或$()中命令不能执行
      • 反引,等同于$( ),但没有方向不支持嵌套
  • 管道和重定向

    • 管道

      • |

        • 把前一条命令的标准输出作为后一条命令的输入
    • 输出

        • 标准输出覆盖重定向
        • 标准输出追加重定向
      • 2>

        • 错误输出重定向
      • &>

        • 所有输出重定向
    • 输入

      • <

        • 输入重定向
        • 进程中表示较高优先级
      • <<

        • 输入结束标识符,通常用来创建有内容的文件
      • <<<

        • 后面的内容将作为标准输入传递给命令。bc <<< 2*3
  • 算数运算符

      • 算数加
      • date +%F,用于连接时间格式
      • 算数减

      • a-Z,连接两个字符表示范围

      • -v,–stdin,命令中表示选项

      • 修改权限

      • 用于文件名,无特殊含义

      • 算数乘
    • /

      • 算数除
      • 根目录,路径分隔符
      • 查找替换
      • 连接IP掩码
    • %

      • 取余,取模
      • 定义时间格式。%H:%M:%S
      • **
      • ^
    • =

      • 权限赋值
      • 定义变量
  • 括号

    • { }

      • 通配符表示集合

        • {a,d}:a和d
        • {a…d}:a到d
      • 占位符,find中-ok,-exec,|xargs

      • 帮助手册中表示必选项

    • [ ]

      • 通配符
      • 帮助手册中表示可选项
    • ( )

      • (命令):开启子shell执行命令,执行结果在父shell中显示
      • $(命令):优先执行()内命令,并将其执行结果作为外面命令的参数
      • $(()):算数运算
  • 其他

    • ~

      • 家目录
    • _

      • 文件名中,无特殊含义
    • \

      • 转义符,取消符号的特殊含义或将字符转成特殊含义(\n)
    • :

      • vim中进入尾行模式
      • 远程连接中用于连接路径,192.168.116.143:/opt/share
      • chown中连接属主属组,user:group
      • shell命令,表示恒为真,也用于占位
    • ,

      • 用于分隔选项,{a,b}
    • .

      • .开头隐藏文件
      • 文件名后缀
      • . 当前目录
      • … 上一级目录
    • !

      • 在[ ]中首位表示取反
      • vim尾行模式表示强制
      • !$调用上一条命令的最后一个参数
    • @

      • 命令提示符中/邮箱,同at
      • vim中替换分隔符,@@@
      • 配置文件或脚本中表示注释
      • 命令提示符中表示管理员用户
      • vim中替换分隔符,###
    • $

      • 位置表示行尾

      • 命令提示符中表示普通用户

      • 预定义变量

        • $$

          • 当前shell的pid
        • $?

          • 上一条命令执行状态的返回值
    • ^

      • 位置表示行首
    • &

      • 命令后面加&表示放到后台运行
      - 空格,分隔命令、选项、参数
    

正则表达式

介绍

  • 正则表达式 (Regular Expression)

    • 正则表达式是一种字符特征的描述方式,用来在文本中匹配到用户想要的东西.
  • 正则表达式与通配符

    • 正则表达式一般用于处理文本内容,常用命令有grep,sed,awk,vim等
    • 通配符一般用于匹配文件名,常用命令有find,ls,cp等
    • 各符号的含义不尽相同.
  • 使用场景

    • vim grep sed awk nginx apache mail垃圾邮件过滤。。。 perl java python 等等都使用正则
  • 构成

    • 1.元字符(基本元字符、扩展元字符)
    • 2.除元字符之外的任意字符都是表示他字面意思的正则表达式
  • 匹配过程

    • 从表达式最左端第一个字符开始,从左到右依次一个一个字符进行匹配

    • 特征:贪婪匹配

      • 符合条件则一直往下匹配,直到不符合时停止

基本元字符

  • 字符匹配

    • .

      • 任意单个字符
    • [ ]

      • 内的任意单个字符
      • [^ ] 首位为^表示取反
      • [a-z] 小写字母
      • [0-9] 数字
      • [A-Z] 大写字母
      • [a-zA-Z] 所有字母
      • [^a-zA-Z0-9] 所有符号
  • 次数匹配


      • 匹配*前面的字符重复0次到多次

        • 匹配0次无意义,需组合使用
        • 如:.* 表示匹配所有
    • {n}

      • {n} 匹配前面的字符刚好重复n次

      • {n,m}前面的字符重复n次到m次

      • {,n} 前面的字符最多重复n次

        • 包含0次
      • {n,} 前面的字符最少重复n次

  • 位置匹配

    • ^ 行首
    • $ 行尾
    • < 词首
    • > 词尾

扩展元字符

    • 前面的字符至少重复1次
  • ?

    • 前面的字符重复0次或1次
  • {}

    • 次数匹配

      • 区别于基本正则不加转义符
  • |

      • egrep -v “#|$”
  • ()

    • 分组匹配

      • echo gogoaa |sed -r “s/(go)+/A/” ->Aaa
  • \n

    • 引用第n个分组的内容

      • 前向: 在正则中引用

        • sed -r “s/(…)c\1/A/” 匹配c前后2个字符一样的内容
      • 后向: 在其他地方引用

        • echo gogoaa |sed -r “s/(go)+/A\1/” ->Agoaa
        • \0表示引用正则中匹配到的所有的内容,等同于&
    • n=1-9

练习

  • head /etc/passwd > /tmp/pass
  1. 删除每行的第一个字符 sed ‘s/.//’ /tmp/pass
  2. 在每行行首插入hello sed -r ‘s/^/hello/’ /tmp/pass
  3. 删除每行的第二个字符 sed -r ‘s/(.)./\1/’ /tmp/pass
  4. 把每个数字用()括起来 如:(1)(2) sed -r ‘s/[0-9]/(&)/g’ /tmp/pass
  5. 把每个数值用()括起来 如:(12) sed -r ‘s/[0-9]+/(&)/g’ /tmp/pass
  6. 删除每行的倒数第二个字符 sed -r ‘s/.(.)$/\1/’ /tmp/pass
  7. 交换每行的第一个和最后一个字符 sed -r ‘s/^(.)(.*)(.)$/\3\2\1/’ /tmp/pass
  8. 删除刚好三个字母的单词 sed -r ‘s/<[a-zA-Z]{3}>//g’ /tmp/pass
  9. 把ro或da替换成A sed -r ‘s/ro|da/A/g’ /tmp/pass
    10.删除每行的最后一个字母 sed -r ‘s/(.*)[a-zA-Z]/\1/’ /tmp/pass
  10. 删除每行的第一个单词(纯字母) sed -r ‘s/[a-zA-Z]+//’ /tmp/pass
  11. 交换第一个和倒数第二个单词(纯字母)
    sed -r ‘s/([a-zA-Z]+)(.)(<[a-zA-Z]+>)(.)([a-zA-Z]+)/\3\2\1\4\5/’ /tmp/pass
    13.将刚好为5个字母,第3个为i,前2个和后2个对称的字符串替换为A,如abiba toiot
    sed -r ‘s/([a-zA-Z])([a-zA-Z])i\2\1/A/g’ a.txt

POSIX字符类

  • [[:digit:]]任何数字
  • [[:xdigit:]]任何十六进制数字
  • [[:alpha:]]任何字母
  • [[:lower:]]任何小写字母
  • [[:upper:]]任何大写字母
  • [[:alnum:]]任何字母或数字
  • [[:cntrl:]]ASCII控制字符(ASCII0~31和ASCII127)
  • [[:punct:]]不属于[:alnum:]和[:cntrl:]的任何字符
  • [[:blank:]]空格或制表符([\t])
  • [[:space:]]任何空白字符,包括空格([\f\n\r\t\v])
  • [[:print:]]任何可打印字符
  • [[:graph:]]同[[:print:]],但不包括空格

sed

介绍

  • 文本的操作

    • sed是一个“非交互式的”面向字符流的编辑器。
    • awk是一种负责模式匹配的程序设计语言,,的典型示例是将数据转换成格式化的报表。
  • sed stream editor

    • 是一种文本编辑器,默认情况下是不会修改原文件的。
    • 也是一种非交互式的编辑器
  • 工作原理

    • 一行一行处理的

      • 在模式空间处理,如果有置换命令再处理保持空间
    • 当从文件中读取一行后,首先放到模式空间中对该行进行相应的处理,处理完将结果输出到屏幕上。然后继续读取下一行内容,直到所有行都读取完毕,sed结束。

用法

  • sed [选项] ‘定位 动作’ 文件…

选项

  • -n

    • 关闭模式空间的输出(默认输出所有行)

    • 单独使用无意义,一般与动作p结合使用

      • sed -n ‘2p’ /tmp/pass
  • -e

    • 可以做多个动作

      • -e ‘动作1’ -e ‘动作2’

        • sed -e ‘2p’ -e ‘5p’ /tmp/pass
      • 等同于 ‘动作1;动作2’

        • sed ‘2p;5p’ /tmp/pass
  • -f

    • 后接sed脚本,指定执行的sed脚本(将模式动作写到文件中)
  • -r

    • 允许使用扩展正则
  • -i

    • 直接作用于原文件,没有输出

    • 在使用-i之前一定先不加-i看看效果

    • -i.bak

      • 修改原文件之前进行备份

定位

  • 无定位,所有的行都执行动作

  • 行号定位

    • 单独的行号

      • 1 处理第1行
      • $ 处理最后一行
    • 起始行,结束行

      • 1,5 处理第1到5行
    • 起始行~步长

      • 每隔多少行操作一次
      • 2~2 从第2行开始,每隔1行
    • 起始行,+N行

      • 表示从起始位置开始,后面的N行都进行处理

      • 3,+5 处理3-8行

        • /root/,+2
  • 正则定位

    • /正则表达式/

      • /^root/ 以root开头的行
    • /正则1/,/正则2/

      • 从第一次匹配到正则1开始,到第一次匹配到正则2之间的所有行,后面仍有满足条件的则继续匹配

      • 如:/root/,/bash/

        • 有root及bash且不在同一行

          • root行开始到bash行结束
        • 无root有bash

          • 无定位结果
        • 有root无bash

          • 从root行开始到文件结束
        • 同一行有root和bash

          • 如果匹配未开始,则该行root生效
          • 如果匹配已开始,则该行bash生效
          • 一行只有一个关键词生效

动作

  • 处理命令

    • d

      • 删除delete

        • sed ‘1d’ 文件名 #删除在指定行
    • p

      • 打印print,打印匹配到的行
    • r

      • 读取read,接文件名,读取到匹配行下方

        • sed ‘/adm/r /etc/hostname’ /tmp/pass
    • w

      • 写write,将匹配到的行覆盖写入文件

        • sed ‘/adm/w /tmp/a.txt’ /tmp/pass
    • a

      • 追加append,在匹配的行下面插入内容

        • sed ‘/adm/a hello’ /tmp/pass
    • i

      • 插入insert,在匹配行的上一行插入内容

        • sed ‘/adm/i hello’ /tmp/pass
    • c

      • 修改change,本行替换

        • sed ‘/adm/c hello’ /tmp/pass
    • y

      • 转换,一一对应转换

        • echo hello |sed ‘y/helo/HELO/’
    • n

      • 处理下一行next,与其他动作组合使用

        • sed ‘/adm/{n;d}’ /tmp/pass
    • q

      • 退出quit,不会再向模式空间读入新的行

        • sed ‘/root/q’ /tmp/pass
      • 只能有1个定位条件

    • s

      • 查找替换

        • ‘定位s/旧内容(正则表达式)/新内容/[修饰符]’

        • 修饰符

          • g

            • 全局替换

              • 2g:从第2个开始全局替换
          • n

            • n=1-512,替换第n个匹配到的内容
          • p

            • 打印s处理的行,与-n联用
          • w

            • 把处理过的行写入到另一个文件
        • 转换

          • \u&

            • upper,匹配内容的第1个字母转换成大写

              • sed -r ‘s/[a-z]/\u&/g’ /tmp/pass
          • \U&

            • upper,匹配内容的所有字母转换成大写

              • sed -r ‘s/.*/\U&/g’ /tmp/pass
          • \l&

            • lower,转换第1个
          • \L&

            • lower,转换所有
      • 分隔符

        • 挨着s的字符,可以是任意

          • s///
          • s@@@
          • s###
  • ! 非

    • 放在命令前面表示取反

      • sed -n ‘8!p’ /tmp/pass #不打印第8行(其他行都打印)

扩展

  • 模式空间

    • 用于处理文本行,最大保存8192字节
  • 保持空间

    • 用来保存已经处理完的文本行,最大保存8192字节
    • 保持空间中默认有一个空行
  • 置换命令

    • h:将模式空间的内容覆盖到保持空间
    • H:将模式空间的内容追加到保持空间
    • g:将保持空间的内容覆盖到模式空间
    • G:将保持空间的内容追加到模式空间
    • x:将模式空间和保持空间中的内容进行交换
  • 示例

      1. 在每行下面添加一个空行 sed ‘G’ a.txt
  1. 将第一行输出到最后一行 sed ‘1h;1d;$G’ a.tx
  2. 交换第一行和第二行内容 sed ‘1h;1d;2G’ a.txt
  3. 将第一行复制到每个偶数行下面 sed ‘1h;2~2G’ a.txt
  4. 交换第一行和第三行的内容 sed ‘1h;1d;2G;2h;2d;3G’ a.txt
  5. 用sed实现tac的效果 sed ‘1!G; ! h ; !h; !h;!d’ a.txt
  • 控制流

    • {} 命令组合 命令用分号分隔 {1h;G} 可以理解为 -e 参数的另一种写法

    • = 打印行号(输入行的号码,而非处理的次数行号) 例如: sed -n ‘2{=;p}’ infile

    • N 追加下一行到模式空间.

    • P 输出多行模式空间的第一部分,直到第一个嵌入的换行符为止。在执行完脚本的最后一个命令之后,模式空间的内容自动输出。P命令经常出现在N命令之后和D命令之前。

    • D 删除模式空间中直到第一个换行符的内容。它不会导致读入新的输入行,相反,它返回到脚本的顶端,将这些指令应用与模式空间剩余的内容。

    • NPD这三个命令能建立一个输入. 输出循环,用来维护两行模式空间,但是一次只输出一行。
      这个循环的目的是只输出模式空间的第一行,然后返回到脚本的顶端将所有的命令应用于模式空间的第二行。没有这个循环,当执行脚本中的最后一个命令时,模式空间中的这两行都将被输出。

      • 删除文件倒数第二行:sed ‘N;$!P;D’ a.txt
      • 删除文件最后两行:sed ‘N; ! P ; !P; !P;!D;$d’ a.txt

awk

awk介绍

  • awk

    • 文本编辑器. 也是一种非交互式的编辑器
    • 一种编程语言
  • 功能

    • 对文本数据进行汇总和处理,是一个报告生成器,能够对数据进行排版
  • 工作模式

    • 行工作模式,读入一行,将整行内容存在“$0”里 记录 行
    • 使用内置变量FS(字段分隔符)分割一行,存到$1-$100 字段 列

与sed主要异同

  • 相同点

    • 语法基本相同
    • 都是流编辑器,工作方式都是读入一行,处理一行
    • 都可以使用正则表达式定位
    • 都允许使用脚本
  • 不同点

    • sed主要处理行,awk主要处理列
    • sed处理动作必须与文件内容相关, awk处理动作可以与文件内容无关, 并且awk的动作要用{} 括起来

awk用法

  • 命令

    • awk [选项] ‘定位 {动作…}’ 文件列表…
  • 选项

    • -F

      • 设定字段分隔符

        • 默认分隔符为空白

        • 单个字符做分隔符

          • -F:
        • 复合分隔符

          • 多个字符组成的分隔符
          • 如:“😕” “[^0-9]+”
        • 同时指定多个分隔符

          • df -h |awk -F “[[:space:]]+|%” ‘//$/{print $5}’
        • 每个字符都是一个字段

          • 即以空为分隔符
          • echo hello |awk -F “” ‘{print $1,$2,$3,$4,$5}’
    • -f

      • 从脚本中读取awk命令
    • -v

      • 自定义变量
  • 动作

    • 默认动作为print

      • awk ‘1’ /etc/passwd
      • 要有定位
    • 输出

      • print

        • 输出

          • 打印内容可以是文件中内容. 也可以和文件无关

            • awk ‘{print “hello”}’ /etc/passwd
          • 不接内容则打印整行$0

            • awk ‘{print}’ /etc/passwd
          • 接不存在的变量则打印空

            • echo |awk ‘{print a}’
        • 要点

          • print输出时默认自带换行符

          • 各个输出字段之间用逗号分隔,而输出时默认以空白分隔

          • print后面如果不指定字段,那么就会打印一整行$0

          • 打印字符串一定要加"",否则识别为变量。数字可不加

            • awk -F: ‘{print $1"的shell是"$7}’ /etc/passwd
          • 可以进行算数运算

            • echo |awk ‘{print 1+2}’
      • prinf

        • 格式化输出

        • 用法

          • printf “format…”,item1,item2,…,itemn

            • format数量与item数量保持一致
          • 格式

            • format

              • %s

                • 表示是字符串
              • %d

                • 表示十进制整数
              • %f

                • 表示浮点数
              • %%

                • 表示%本身
              • %x

                • 表示十六进制数
              • %o

                • 表示八进制数
              • %c

                • 表示字符
            • 修饰符

              • 数字

                • 表示显示宽度,如:%5d
                • 左对齐,默认是右对齐,如:%-5s

        • 要点

          • 与print不同的是printf需要指定格式
          • printf默认无换行符,需要时候手动添加"\n"
          • 格式(format)是用来指定后面的每个item的输出格式
          • printf默认没有输出分隔符
        • 示例

          • awk -F: ‘{printf “%-18s%-5s%-5s\n”,$1,$3,$4}’ /etc/passwd
  • 定位

      • 每一行都处理
    • 单表达式

      • 表达式为真,则执行动作

      • 数值比较

        • 直接数值比较

          • < >= <= == !=

          • 如:$3<10
        • 算术运算后比较

                • / % ** ^
          • 如:$3%2==1
      • 字符串比较

        • 精确匹配

          • ==

            • $1==“root”
          • !=

            • $1!=“root”
          • 注意字符串加“”,数字可不加

        • 正则匹配

          • ~

            • 匹配正则

              • $3~/7/ #某一列匹配
              • /root/ #整行匹配,省略$0~
          • !~

            • 不匹配正则

              • x !~ /y/
          • 注意正则要写在//中

    • 多表达式

      • exp1&&exp2

        • exp1和exp2同时为真
      • exp1||exp2

        • exp1或exp2有一个为真
      • exp1,exp2

        • 从exp1为真到exp2为真

          • awk ‘NR2,NR5{print}’
    • 恒真

      • 非空字符串
      • 非0整数
      • 恒真表达式
  • 示例

      1. 打印uid在59到99之间的用户名和uid(包含59,但不包含99) awk -F: ‘$3>=59&&$3<99{print $1,$3}’ /etc/passwd
  1. 打印uid和gid不相同的用户的用户名,uid及gid awk -F: ‘$3!=$4{print $1,$3,$4}’ /etc/passwd
  2. 交换passwd文件的第一个字段和第二个字段(以冒号为分隔) awk -F: ‘{print $2":"$1}’ /etc/passwd
  3. 打印100以内能够被7整除以及包含7的数: 如7,14,17… seq 100 |awk ‘$0%7==0||/7/{print}’
    5.打印/etc/fstab中含有boot的行 awk ‘/boot/{print}’ /etc/fstab

awk操作符

  • 算数运算符

    • -x:表示负数 +x(x):表示正数
    • x+y x-y x*y x/y x%y x**y x^y (x的y次幂)
  • 关系运算符

    • 数值

      • < >= <= == !=

    • 字符串

      • == != ~ !~
  • 逻辑运算符

    • && || !
  • 赋值运算符

    • = += -= *= /= %= **= ^=

      • a+=$2 等效于 a=a+$2
    • ++ –

      • a++

        • 先赋值,再自增
      • ++a

        • 先自增,再赋值

awk变量

  • 内置变量

    • $0

      • 表示一整行的内容
    • $1~$100

      • 表示第N列
    • 与记录相关

      • FS

        • Field Separator:字段分隔符,默认是空白
        • -F指定,或者BEGIN{FS=“”}定义
      • RS

        • Record Separator:记录分隔符,默认是换行符
        • echo “ni:hao” |awk ‘BEGIN{RS=“:”}{print $1}’
      • OFS

        • Output,输出时的字段分隔符,默认空格
      • ORS

        • 输出时的记录分隔符,默认换行符
    • 与数据相关

      • NR

        • 记录数,awk所处理的记录的总数(多个文件时累加)

          • awk ‘{print NR,$0}’ a.txt b.txt
        • NR在很多情况下可以看成行号

      • FNR

        • 当前文件所处理的记录数

          • awk ‘{print FNR,$0}’ a.txt b.txt
      • NF

        • 当前行的字段总数

          • $NF

            • 当前行最后一个字段的值
          • $(NF-1)

            • 当前行倒数第二个字段的值
  • 自定义变量

    • 命名

      • 由字母、数字、下划线组成,区分大小写,不能以数字开头
      • 不要使用关键字,最好见名知意
      • 变量可以先定义再使用,也可以直接使用(整型)
    • 变量定义

      • 变量名=数值

        • awk ‘BEGIN{a=1;print a}’
      • 变量名=“字符串”

        • awk ‘BEGIN{a=“hello”;print a}’
    • 变量引用

      • 直接使用变量名
    • 取消变量

      • delete 变量名
    • 变量的长度

      • length(变量名)
  • 练习

      1. 打印passwd文件的奇数行的行号和内容 awk ‘NR%2{print NR,$0}’ /etc/passwd
  1. 打印每行的倒数第3个字段 awk -F: ‘{print $(NF-2)}’ /etc/passwd
  2. 从第一行开始,每隔三行打印一次(即打印1 4 7这样的行) awk -F: ‘NR%3==1{print NR,$0}’ /etc/passwd
  3. 统计UID和GID不相等的行数(不要用wc命令) awk -F: ‘$3!=$4{count++}END{print count}’ /etc/passwd
  4. 统计/etc目录下所有普通文件的总大小(M) ll /etc |awk ‘/^-/{sum+=$5}END{print sum/1024/1024"M"}’
    6.统计一个字符串的字符数 echo kjshfhhfl |awk -F “” ‘{print NF}’ 或awk ‘{print length($0)}’

awk特殊模式

  • 用法

    • awk [选项] ‘BEGIN{动作}模式{动作}END{动作}’ 文件列表

    • 示例

      • BEGIN{count=0}{count++}END{print count}’ /etc/passwd
  • 类型

    • BEGIN{}

      • 在读取文件之前就执行,并且只执行一次

      • 一般用于初始化分隔符、定义变量、定义数组、打印表头等

      • BEGIN单独存在,后面不需要加文件

        • awk ‘BEGIN{print 1+2}’
    • 标准模式{}

      • 这一部分可能会执行多次,处理内容
    • END{}

      • 在处理完文本之后执行,并且只执行一次

      • 汇总数据 比如:打印总成绩. 打印平均成绩等等

      • END单独存在,后面必须接文件,可以是空文件

      • 示例

        • awk ‘END{print NR}’ /etc/passwd

awk脚本

  • BEGIN{
      SUM=0
    
    }
    {
    SUM++
    }
    END{
    print SUM
    }

awk流控制

  • if

    • 单分支

      • 语法格式

        • awk ‘{if(条件表达式){动作}else{动作}}’ file
      • 脚本形式

        • {
          if (条件表达式) {
          动作
          }
          else {
          动作
          }
          }
    • 多分支

      • 语法格式

        • awk ‘{if(条件表达式){动作}else if(条件表达式){动作}else{动作}}’ file
      • 脚本形式

        • {
          if (条件表达式) {
          动作
          }
          else if (条件表达式) {
          动作
          }
          else {
          动作
          }
          }
  • 循环

    • while

      • 语法格式

        • awk ‘{while(条件){动作;变量更新}}’ file
      • 脚本形式

        • {
          while (条件) {
          动作
          变量的更新
          }
          }
    • for

      • 语法一

        • {
          for(变量初值;判断条件;变量的更新 {
          动作
          }
          }
      • 语法二

        • {
          for(变量 in 列表) {
          动作
          }
          }
    • 循环控制语句

      • continue

        • 跳出本次循环,提前进入下一个循环
      • break

        • 跳出当前循环
      • exit

        • 退出当前脚本,退出当前程序
      • next

        • 跳过本行
    • 示例

      • 倒序输出passwd文件的每一列

      • 命令形式

        • awk -F: ‘{for(i=NF;i>1;i–){printf $i":"};print $1}’ /etc/passwd
      • 脚本形式

        • vim awk
          BEGIN{FS=“:”}
          {
          for(i=NF;i>1;i–) {
          printf $i":"
          }
          print $1
          }
          awk -f awk /etc/passwd
  • 练习

      1. 将passwd文件的第一行的每个字段纵向打印 awk -F: ‘NR==1{for(i=1;i<=NF;i++){print $i}}’ /etc/passwd
  1. 倒序输出passwd文件的每一列 awk -F: ‘{for(i=NF;i>1;i–){printf $i":"};print $1}’ /etc/passwd
  2. 输出文件中每行的最大值 awk ‘{a=0;for(i=1;i<=NF;i++){if(KaTeX parse error: Expected '}', got 'EOF' at end of input: i>a){a=i}};print a}’ a.txt
  3. 打印99乘法口诀表 seq 9 |awk ‘{for(i=1;i<=NR;i++){printf i"“NR”="iNR"\t"};print a}’

awk数组

  • 介绍

    • awk数组为关联数组,即可以使用字符串作下标
    • 常用于收集信息, 计算次数等
  • 数组的定义

    • 数组名[下标]=值
  • 数组长度

    • length(数组名)
  • 数组的取消

    • delete 数组名

      • 取消整个数组
    • delete 数组名[下标]

      • 取消数组中的一个元素
    • 数组的遍历

      • for (变量 in 数组名){ print 数组名[变量]}

      • 此处变量的取值列表为数组的下标

      • 示例

        • 统计每个shell的数量
        • awk -F: ‘{count[$NF]++}END{for(i in count){print count[i],i}}’ /etc/passwd
        • 使用awk实现tac的功能
        • awk ‘{line[NR]=$0}END{for(i=NR;i>0;i–){print line[i]}}’ /tmp/pass

调用shell变量

  • awk

    • -v定义变量

      • echo |awk -v name=$USER ‘{print name}’
      • 只能传递到{}中
    • 使用‘’将其暴露在shell中

      • awk -F: ‘/^’$USER’/{print $1,$3,$4}’ /etc/passwd
  • sed

    • 单引换成双引

      • sed -n “/^$USER/p” /etc/passwd

shell

变量

  • 变量介绍

    • 变量代表一个有名字的、具有特定属性的一个存储单元
    • 变量用来存放数据,也就是存放变量的值
    • 变量的值可以改变
    • 变量有特定的类型,类型决定了存储单元的大小和变量值的范围,运算符可应用于变量上
    • 从本质上看,变量代表了一段可操作的内存,也可以认为变量是内存的符号化表示
  • 变量命名

    • 组成

      • 字母、数字、下划线
      • 不能以数字开头
    • 规范

      • 不要使用关键字,最好见名知义
  • 变量操作

    • 查询

      • echo $变量名
    • 调用

      • ${变量名称}
      • “$变量名称”
      • 无歧义情况下{}或“”可省略
    • 修改

      • 重新定义
    • 删除

      • unset 变量名
  • 变量类型

    • 本地变量

      • 作用范围

        • 只在当前shell或脚本中生效
      • 定义方法

        • 变量名=变量值
        • 注意:等号两边一定不能有空格
        • 同一变量名多次定义,后面的会覆盖之前的
    • 环境变量

      • 作用范围

        • 命令定义

          • 当前用户的当前shell及其子shel
          • 切换用户或退出当前shell则失效
        • 配置文件

      • 定义方法

        • 命令定义

          • 直接定义

            • export 变量名=变量值
            • export file_name=a.txt
          • 将已有的本地变量导出成环境变量

            • file_name=a.txt
              export file_name
        • 配置文件

      • 查看

        • 查看所有环境变量

          • env
          • export
        • 查看所有变量

          • set
      • 常见系统环境变量

        • PATH

          • 系统查找外部命令的路径(可自定义脚本放到这些路径下)
          • /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
        • USER

          • 当前用户
        • UID

          • 当前用户uid
        • HOME

          • 当前用户家目录
        • HOSTNAME

          • 当前主机名
        • PWD

          • 当前路径
        • PS1

          • 定义命令提示符
        • EDITOR

          • 系统调用的编辑器,默认vi
          • echo “export EDITOR=vim” >> /etc/profile
    • 位置变量

      • $0

        • 表示当前运行的脚本或者命令本身
      • 1   1~ 1 n

        • 表示脚本的位置参数, shell脚本在执行时, 会将参数依次赋值给$1, $2, … , $n
        • 10及以上要用{},如${10},否则会识别成$1和0
      • $#

        • 表示参数个数
      • @ 和 @和 @*

        • 表示参数的列表

        • $@

          • 将每一个参数看成独立的字符串打印
        • $*

          • 将所有参数看成一个字符串
        • 示例

          • 一组参数为1 2 3 4 5

          • for i in “$*”

            • 相当于 for i in “1 2 3 4 5”
          • for i in “$@”

            • 相当于 for i in “1” “2” “3” “4” “5”
    • 预定义变量

      • $$

        • 当前shell的pid
      • $?

        • 上一条命令执行状态的返回值
        • 0:正确执行
        • 1-255:错误执行
    • 变量替换

      • ${parameter:-word}

        • a=${b:-10}
        • 如果变量b为空或未定义,则a=10;如果b有非空值,则a=b,b不变
      • ${parameter:=word}

        • a=${b:=10}
        • 如果变量b为空或未定义,则a=10,b=10;如果b有非空值,则a=b,b不变
      • ${parameter:+word}

        • a=${b:+10}
        • 如果变量b为空或未定义,则a=b;如果b有非空值,则a=10,b不变
      • ${parameter:?message}

        • a=${b:?error}
        • 如果变量b为空或未定义,则将error作为标准错误打印出来;如果b有非空值,则a=b
    • 变量切片

      • 字符数

        • eg:a=12345678

        • ${变量名:N}

          • 从变量头部开始, 切掉N个字符
          • echo ${a:5} # 把前面5位去掉->678

        • ${变量名: -N}

          • 从后面开始取N位,注意空格
          • echo ${a: -3} # 从后面开始取3位->678

        • ${变量名:N1:N2}

          • N2为正:前面切N1个取N2个;N2为负:前面切N1个,后面切N2个
          • echo ${a:3:4} # 把前面3位去掉,取4位内容->4567

      • 字符串

        • eg:a=12233221345

        • ${变量#关键词}

          • 切除最短的符合关键词的字符串
          • echo ${a#1*3} ->3221345

        • ${变量##关键词}

          • 切除最长的符合关键词的字符串
          • echo ${a##1*3} ->45

        • ${变量%关键词}

          • 从后面开始匹配,切除最短的符合关键词的字符串
          • echo ${a%3*} ->12233221

        • ${变量%%关键词}

          • 从后面开始匹配,切除最长的符合关键词的字符串
          • echo ${a%%3*} ->122

        • ${变量/旧字符串/新字符串}

          • 匹配第一个最长的旧字符串,替换成新字符串
          • echo ${a/3/A}:第一次匹配的被替换->122A3221345

        • ${变量//旧字符串/新字符串}

          • 匹配所有的旧字符串,替换成新字符串
          • echo ${a//1/A}:全局的匹配被替换->122AA221A45

常用命令

  • read

    • 用法

      • read [选项] 变量名
      • 读取键盘输入的值,并赋给变量
    • 选项

      • -p " "

        • 打印提示信息
      • -s

        • 输入不显示(隐藏输入内容)
      • -n N

        • -n6

          • 限制输入字符数
      • -t

        • 限定输入时间,默认单位是秒
      • -a array

        • 接收多个输入将其定义为数组
    • 示例

      • #!/bin/bash
        read -sp “请输入密码:” userPasswd #提示输入内容并隐藏
        echo #换行
        echo “你输入的密码是:” $userPasswd #打印输入内容
  • echo

    • 作用

      • 最常用的输出命令,默认最后带一个换行符。也常用于打印空行或换行
      • 帮助信息:help echo
    • 选项

      • -n 取消换行符

      • -e 支持转义字符

        • \n

          • 换行符new line
          • echo -e “1hang\n2hang” #输出多行
        • \t

          • 制表符tab

            • echo -e “a\taaa\nbbb\tb” #对齐
        • \r

          • 光标回到行首,要与-n选项结合使用
        • \b

          • 删除前一个字符
    • 扩展

      • 带颜色输出

        • 字体颜色

          • echo -e “\033[字体颜色号m文本内容\033[0m”
        • 背景颜色

          • echo -e “\033[背景颜色号;字体颜色号m文本内容\033[0m”
        • \033可用\e代替

      • 颜色号

        • 字体颜色:30-37;90-97
        • 背景颜色:40-47
  • printf

    • 用法

      • printf 格式 参数列表
      • 指定格式打印输出内容
    • 格式

      • %-10s

          • 表示左对齐,没有则表示右对齐
        • 10 表示列宽度
        • s 表示输出参数为字符串
      • %-10.2f

        • f 表示输出参数为浮点数
        • .2 指保留2位小数
      • %d

        • 用于十进制整数
      • 默认没有换行符,可加上\t \n,格式内容加上引号

    • 参数列表

      • 字符串或变量值,多个参数间分隔符为空格
      • 格式只指定了一个内容,多出的内容仍然会按照该格式输出
    • 示例

      • printf “%-5d%-5s\n” 1000 “abc”
      • printf “%s%s%s\n” a b c d e f g
  • test

    • 用法

      • test expression
      • [ expression ]
      • 在脚本中用于条件判断
    • 返回值

      • 0 - 当表达式为真时
      • 1 - 当表达式为假时
    • 判断类型

      • 字符串比较

        • -n:not zero

          • [ –n “字符串”  ] # 字符串的长度非零则为真

          • 示例

            • name=

[ -n “$name” ]

echo $?

1

		- -z:zero

			- [  –z  "字符串"   ]  # 字符串的长度为零则为真
			- 示例

				- #!/bin/bash

read -sp “请输入用户名:” userName
echo
[ -z “$useraName” ] && echo “输入不能为空!” && exit 1
echo “你输入的名称是:” $userName

		- ==:相同

			- [ "字符串1" == "字符串2"  ]  # 字符串完全相同则为真

		- !=:不相同

			- [ "字符串1" != "字符串2"   ]  # 字符串不同则为真

		- 注意

			- 字符串比较要加引号

	- 数值比较 

		- -eq:==

			- [  n1 -eq  n2  ]  # n1等于n2则为真

		- -ne:!=

			- [  n1 -ne  n2  ]  # n1不等于n2则为真

		- -ge:>=

			- [  n1 -ge  n2  ]  # n1大于等于n2则为真

		- -gt:>

			- [  n1 -gt   n2  ]  # n1大于n2则为真

		- -le:<=

			- [  n1 -le   n2  ]  # n1小于等于n2则为真

		- -lt:<

			- [  n1 -lt   n2   ]  # n1小于n2则为真

		- 注意

			- 数值判断可不加引号
			- 使用(( ))可用符号进行比较

				- (( n1 >= n2 ))

	- 判断文件

		- -e:文件存在

			- [  –e  File  ]  # 文件存在则为真

		- -d:目录文件

			- [  –d  File  ]  # 文件存在并且是目录则为真

		- -f:普通文件

			- [  –f  File  ]  # 文件存在并且是普通文件则为真

		- -r:文件可读

			- [  –r  File  ]  # 文件存在并且可读则为真

		- -w:文件可写

			- [  –w File ]  # 文件存在并且可写则为真

		- -x:文件可执行

			- [  –x  File  ]  # 文件存在并且可执行则为真

		- -h -L:软链接

			- [  –h  File  ]  # 文件存在并且是软链接则为真

	- 逻辑判断

		- 与:多个表达式同时为真则为真

			- [ exp1 ]  &&  [ exp2 ]
			- [[  exp1  &&  exp2  ]]
			- [  exp1  -a  exp2  ]

		- 或:多个表达式有一个为真则为真

			- [ exp1 ]  ||  [ exp2 ]
			- [[  exp1  ||  exp2  ]]
			- [  exp1  -o  exp2  ]

		- 非:判断结果取反

			- [  ! n1 -lt   n2   ]  # n1小于n2则为假

	- 特殊判断

		- 判断是否纯数字

			- [[  "$phone" =~ ^[0-9]+$  ]]
			- [[  "$phone" =~ ^[[:digit:]]+$  ]]
			- expr 1 + $number

		- 判断是否纯字母

			- [[  "$phone" =~ ^[a-Z]+$  ]]

		- ~ 对后面的正则表达式匹配
  • expect

    • 作用

      • 把交互式操作变成非交互式
    • 命令

      • expect << -eof

        • expect命令开始
      • spawn su - user

        • 执行命令
      • expect “password:”

        • 捕获关键字
      • exp_continue

        • 继续捕获
      • send “\n”

        • 发送字符串
      • expect eof

        • 捕获结束
      • eof

        • expect命令结束,与开始时定义的标识符一致
      • interact

        • 执行完成后保持留在远程机器上
    • 格式

      • 常规

        • expect <<- eof
          spawn command1
          expect “xxx”
          send “xxx”

          spawn command2

          expect eof
          eof
      • 分支

        • expect {
          “xxx” { send “xxx”;
          expect “xxx” send “xxx”

          exp_continue #继续捕获下一个分支
          }
          “yyy” { send “yy”}
          }
    • 示例

      • #!/bin/bash
        /usr/bin/expect <<EOF
        set timeout 300
        spawn ssh-keygen
        expect “Enter file in which to save the key (/root/.ssh/id_rsa):”
        send “\n”
        expect “Enter passphrase (empty for no passphrase):”
        send “\n”
        expect “Enter same passphrase again:”
        send “\n”

spawn ssh-copy-id 192.168.1.250
expect {
“yes/no” { send “yes\n”; exp_continue }
“root@192.168.1.250’s password:” { send “qfedu\n”}
}

expect eof
EOF

  • 其他

    • set

      • 放在#!的下方, 用于对脚本的设置

      • 选项

        • -x

          • 调试模式,类似于sh -x
        • -u

          • 试图调用未定义的变量就退出
        • -e

          • 若有命令执行失败则退出
    • eval

      • 将参数作为独立的命令来执行
      • 如: 直接执行 $name=20 会出错, 前面加上eval 就可以了
    • sleep

      • 后接数字(可接小数), 表示脚本暂停一段时间
      • 默认单位为s, 也可接具体的单位, 如 m, h, d
      • 如: sleep 3
    • basename

      • 基本名, 这个命令会去掉文件名前面的路径
      • 如: basename /a/b/c/d.txt 执行的结果为 d.txt
    • dirname

      • 目录名, 根基本名相反, 只保留文件的路径
      • 如: dirname /a/b/c/d.txt 执行的结果为 /a/b/c
    • timeout

      • 指定执行命令的超时时间, 默认单位为s
      • 如: timeout 3s ping 192.168.10.20
    • shift

      • 略过指定数量参数, 默认为1
      • 如: shift 1 这个命令将会略过所接的第一个参数, 将第二个参数赋值为$1

流控制

  • 分支判断

    • if判断

      • 单分支

        • if 条件表达式 ;then
          动作块
          fi

          • if [ ! -d /test ];then
            mkdir /test
            fi
      • 双分支

        • if 条件表达式 ;then
          动作块
          else
          动作块
          fi

          • if [ ! -d /test ];then
            mkdir /test
            else
            echo “目录/test已存在”
            fi
      • 多分支

        • if 条件表达式1;then
          动作块1
          elif 条件表达式2;then
          动作块2
          … #elif可以有多个
          else
          动作块n
          fi
      • 注意

        • if和fi要成对出现, 脚本里有几个if就得有几个fi
        • 每一个条件表达式后面都要加then
        • 无论有多少个分支, 最多只有基中一个动作块会执行(最先满足条件的动作块)
    • case判断

      • 单变量

        • case $变量 in
          值1)
          动作块1 ;;
          值2)
          动作块2 ;;

          值n)
          动作块n ;;
          esac

          • read -p “请输入你的选择:” choice
            case $choice in
            [yY][eE][sS]|[yY]) #yes无论大小写
            echo yes ;;
            [nN][oO]|[nN])
            echo no ;;
            *)
            echo “only yes or no” ;;
            esac
      • 多变量

        • 多个变量同时匹配,可使用空格或逗号分隔多个变量及值,注意上下一致

        • 用法

          • case 变量 1 , 变量1, 变量1,变量2 in
            值11,值12)
            动作块1 ;;
            值21,值22)
            动作块2 ;;

            值n1,值n2)
            动作块n ;;
            esac
  • 循环

    • for循环

      • 用法

        • for 变量名 in 列表 ;do
          动作块
          done

          • sum=0
            for number in {1…100};do
            let sum+=number
            done
            echo $sum
        • c写法

          • for ((i=1;i<=10;i++));do
            动作块
            done
        • 变量在列表中取值,每取一个值,做一遍动作块里的动作

      • 列表

        • 普通

          • 1 2 3 4 5
          • {1,3,5,7,9}
          • {1…100}
        • seq

          • seq N

            • 从1到N, 步长为1
          • seq N M

            • 从N到M,步长为1
          • seq N S M

            • 从N到M,步长为S

            • 示例

              • 100以内奇数:seq 1 2 100
              • 100以内偶数:seq 2 2 100
        • 分隔符

          • 空格、\t、\n
    • 变量更新

      • let

        • 作用

          • 声明后面是算数运算
          • 算术运算中若变量未定义值则默认为0
        • let a+=b

          • a=a+b
        • let a++

          • a,a=a+1,先赋值再自增
        • let ++a

          • a=a+1,a,先自增再赋值
      • 示例

        • #a=10;echo “$a $((a++)) $a”
          #10 10 11
        • #a=10;echo “$a $((++a)) $a”
          #10 11 11
    • while循环

      • 条件循环

        • 用法

          • while 条件表达式 ;do
            循环体
            done
        • 示例

          • i=1
            while [ $i -le 10 ] ;do
            echo $i
            let i++
            done
        • 注意

          • 循环体部分一定要有变量的更新,否则死循环
      • 遍历循环

        • 用法

          • while read 变量名 ;do
            动作块
            done < /path/file_name
          • ls /test |while read 变量名 ;do
            动作块
            done
        • 示例

          • while read line ;do
            userName=$(echo $line|awk -F: '{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 1}̲') uid=(echo $line|awk -F: '{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 3}̲') gid=(echo $line|awk -F: '{print KaTeX parse error: Expected 'EOF', got '}' at position 2: 4}̲') printf "%-22…userName uid: u i d g i d : uid gid: uidgid:gid
            done < /etc/passwd
        • 遍历文件,在遍历时,将整行的内容赋值给变量

    • until循环

      • 用法

        • until 条件表达式 ;do
          循环体
          done
      • until与while相反

        • while:当条件为真,执行循环体
        • until:当条件为真,退出循环
    • 循环控制语句

      • continue

        • 作用

          • 退出本次循环,直接进入下一次循环
          • 意味着本次循环体中continue以下的语句将被跳过
          • 变量的更新放在continue前面,否则会进入死循环
        • 示例

          • n=0
            while :;do #恒为真
            let n++
            [ $n -eq 5 ] && continue
            echo $n
            [ $n -eq 10 ] && break
            done
      • break

        • 跳出整个循环,并不结束脚本, 循环以下的内容还会继续执行
      • exit

        • 退出脚本

数组array

  • 介绍

    • 数组是可以保存一组值的变量,数组中的值使用下标(第几个)来区分。
    • 索引数组:以整数为下标。下标默认从0开始。
    • 关联数组:以字符串为下标。
  • 索引数组

    • 定义数组

      • 批量定义

        • nums=(2 5 8) # 下标从0开始,依次递增
        • user=(awk -F: '{print $1}' /etc/passwd)
      • 单个定义

        • nums[100]=hello #定义下标100的元素
    • 调用数组

      • 单个

        • ${nums[下标]}
        • ${name[变量]}
        • ${name[-1]} #-1指数组中最后一个元素
      • 全部

        • ${nums[*]}
        • ${nums[@]}
    • 查看数组

      • 数组的下标

        • echo ${!nums[*]}

          • 按顺序列出所有值的下标
      • 数组长度

        • echo ${#nums[@]} # 值的个数
    • 数组的遍历

      • 遍历值

        • for i in ${user[@]};do echo $i;done
      • 遍历下标

        • for i in ${!user[@]};do echo ${user[i]};done
    • 取消数组

      • unset nums[100] # 取消数组中的一个元素
      • unset nums # 取消整个数组
  • 关联数组

    • 定义关联数组

      • 声明关联数组

        • declare -A tom
      • 元素赋值

        • tom[age]=20
          tom[sex]=male
          tom[addr]=“guangzhou”
  • 应用

    • 变量更新

      • #!/bin/bash
        chars=({a…z})
        word=
        i=1
        len=${1:-10}
        while [ $i -le l e n ] ; d o r a n = len ];do ran= len];doran=[RANDOM%KaTeX parse error: Expected '}', got '#' at position 2: {#̲chars[@]}] word…word${chars[ran]} #变量更新
        let i++
        done
        echo $word
    • 统计数量

      • #!/bin/bash
        declare -A array
        for i in awk -F: '{print $NF}' /etc/passwd;do
        let array[$i]++ #每遍历一个值,相同下标的元素值+1
        done

for j in ${!array[@]};do
echo KaTeX parse error: Expected '}', got 'EOF' at end of input: {array[j]} $j
done

函数function

  • 介绍

    • 函数是完成某个特定功能的一段代码
    • 函数不能独立运行, 需要使用时通过函数名调用函数
  • 定义函数

    • function_name() {
      代码集
      }
  • 调用函数

    • 脚本内调用

      • 直接使用函数名
    • 调用外部函数

      • 点执行source
    • 示例

      • 例如:用函数写一个添加一个固定用户的脚本,然后在脚本中调用它
        #!/bin/bash
        USERADD() { # 定义函数
        user_name=test1
        if id $user_name &> /dev/null
        then
        echo “User $user_name exist”
        else
        useradd $user_name
        echo “user $user_name added”
        fi
        }

USERADD # 调用函数

  • 自定义函数状态返回值

    • 当我们需要函数执行完成后给出返回值,不能用exit,要使用return
  • 函数的传参

    • 函数是一种特殊的命令,在执行时,也可以向函数体内传递参数。同shell脚本的位置参数。
  • 函数中的变量

    • 全局变量

      • 直接定义,在整个脚本中生效
    • 局部变量

      • 在函数中使用local定义,局部变量仅在函数内生效
    • 示例

      • #!/bin/bash
        function HELLO(){
        local a=10 # 局部变量
        b=20 # 全局变量
        echo “In function $a is $a”
        echo “In function $b is $b”
        }

HELLO
echo “$a is $a”
echo “$b is $b”

应用

  • 不重复的随机数

    • grep -qw过滤,重复则continue

    • 从数组中取,取后unset该元素

    • 插眼遍历数组,重复则改变眼的值

      • #!/bin/bash
        red=()
        j=0
        while :;do
        ran=$[RANDOM%33+1]
        flag=0 #插眼
        for i in ${red[@]};do
        [ $i -eq $ran ] && flag=1
        done
        [ KaTeX parse error: Expected 'EOF', got '&' at position 14: flag -eq 0 ] &̲& red[j]=$ran && let j++
        [ $j -eq 6 ] && break
        done
        echo ${red[@]}
    • 用随机数做数组下标,重复则会覆盖该下标元素

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值