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用户 - 第一行#!开头指定解释器,便于移植
- #后面表示注释内容,增加可读性
- #!/bin/bash
-
加上可执行权限
- 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
- 删除每行的第一个字符 sed ‘s/.//’ /tmp/pass
- 在每行行首插入hello sed -r ‘s/^/hello/’ /tmp/pass
- 删除每行的第二个字符 sed -r ‘s/(.)./\1/’ /tmp/pass
- 把每个数字用()括起来 如:(1)(2) sed -r ‘s/[0-9]/(&)/g’ /tmp/pass
- 把每个数值用()括起来 如:(12) sed -r ‘s/[0-9]+/(&)/g’ /tmp/pass
- 删除每行的倒数第二个字符 sed -r ‘s/.(.)$/\1/’ /tmp/pass
- 交换每行的第一个和最后一个字符 sed -r ‘s/^(.)(.*)(.)$/\3\2\1/’ /tmp/pass
- 删除刚好三个字母的单词 sed -r ‘s/<[a-zA-Z]{3}>//g’ /tmp/pass
- 把ro或da替换成A sed -r ‘s/ro|da/A/g’ /tmp/pass
10.删除每行的最后一个字母 sed -r ‘s/(.*)[a-zA-Z]/\1/’ /tmp/pass - 删除每行的第一个单词(纯字母) sed -r ‘s/[a-zA-Z]+//’ /tmp/pass
- 交换第一个和倒数第二个单词(纯字母)
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:将模式空间和保持空间中的内容进行交换
-
示例
-
- 在每行下面添加一个空行 sed ‘G’ a.txt
-
- 将第一行输出到最后一行 sed ‘1h;1d;$G’ a.tx
- 交换第一行和第二行内容 sed ‘1h;1d;2G’ a.txt
- 将第一行复制到每个偶数行下面 sed ‘1h;2~2G’ a.txt
- 交换第一行和第三行的内容 sed ‘1h;1d;2G;2h;2d;3G’ a.txt
- 用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整数
- 恒真表达式
-
-
示例
-
- 打印uid在59到99之间的用户名和uid(包含59,但不包含99) awk -F: ‘$3>=59&&$3<99{print $1,$3}’ /etc/passwd
-
- 打印uid和gid不相同的用户的用户名,uid及gid awk -F: ‘$3!=$4{print $1,$3,$4}’ /etc/passwd
- 交换passwd文件的第一个字段和第二个字段(以冒号为分隔) awk -F: ‘{print $2":"$1}’ /etc/passwd
- 打印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(变量名)
-
-
练习
-
- 打印passwd文件的奇数行的行号和内容 awk ‘NR%2{print NR,$0}’ /etc/passwd
-
- 打印每行的倒数第3个字段 awk -F: ‘{print $(NF-2)}’ /etc/passwd
- 从第一行开始,每隔三行打印一次(即打印1 4 7这样的行) awk -F: ‘NR%3==1{print NR,$0}’ /etc/passwd
- 统计UID和GID不相等的行数(不要用wc命令) awk -F: ‘$3!=$4{count++}END{print count}’ /etc/passwd
- 统计/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
- vim awk
-
-
-
练习
-
- 将passwd文件的第一行的每个字段纵向打印 awk -F: ‘NR==1{for(i=1;i<=NF;i++){print $i}}’ /etc/passwd
-
- 倒序输出passwd文件的每一列 awk -F: ‘{for(i=NF;i>1;i–){printf $i":"};print $1}’ /etc/passwd
- 输出文件中每行的最大值 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
- 打印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
- file_name=a.txt
-
-
配置文件
-
-
查看
-
查看所有环境变量
- 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
-
-
变量切片
-
常用命令
-
read
-
用法
- read [选项] 变量名
- 读取键盘输入的值,并赋给变量
-
选项
-
-p " "
- 打印提示信息
-
-s
- 输入不显示(隐藏输入内容)
-
-n N
-
-n6
- 限制输入字符数
-
-
-t
- 限定输入时间,默认单位是秒
-
-a array
- 接收多个输入将其定义为数组
-
-
示例
- #!/bin/bash
read -sp “请输入密码:” userPasswd #提示输入内容并隐藏
echo #换行
echo “你输入的密码是:” $userPasswd #打印输入内容
- #!/bin/bash
-
-
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
[ -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 <<- eof
-
分支
- expect {
“xxx” { send “xxx”;
expect “xxx” send “xxx”
…
exp_continue #继续捕获下一个分支
}
“yyy” { send “yy”}
}
- expect {
-
-
示例
- #!/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”
- #!/bin/bash
-
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 [ ! -d /test ];then
-
-
双分支
-
if 条件表达式 ;then
动作块
else
动作块
fi- if [ ! -d /test ];then
mkdir /test
else
echo “目录/test已存在”
fi
- if [ ! -d /test ];then
-
-
多分支
- if 条件表达式1;then
动作块1
elif 条件表达式2;then
动作块2
… #elif可以有多个
else
动作块n
fi
- if 条件表达式1;then
-
注意
- 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
- read -p “请输入你的选择:” choice
-
-
多变量
-
多个变量同时匹配,可使用空格或逗号分隔多个变量及值,注意上下一致
-
用法
- case
变量
1
,
变量1,
变量1,变量2 in
值11,值12)
动作块1 ;;
值21,值22)
动作块2 ;;
…
值n1,值n2)
动作块n ;;
esac
- case
变量
1
,
变量1,
变量1,变量2 in
-
-
-
-
循环
-
for循环
-
用法
-
for 变量名 in 列表 ;do
动作块
done- sum=0
for number in {1…100};do
let sum+=number
done
echo $sum
- sum=0
-
c写法
- for ((i=1;i<=10;i++));do
动作块
done
- for ((i=1;i<=10;i++));do
-
变量在列表中取值,每取一个值,做一遍动作块里的动作
-
-
列表
-
普通
- 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
- #a=10;echo “$a $((a++)) $a”
-
-
while循环
-
条件循环
-
用法
- while 条件表达式 ;do
循环体
done
- while 条件表达式 ;do
-
示例
- i=1
while [ $i -le 10 ] ;do
echo $i
let i++
done
- i=1
-
注意
- 循环体部分一定要有变量的更新,否则死循环
-
-
遍历循环
-
用法
- while read 变量名 ;do
动作块
done < /path/file_name - ls /test |while read 变量名 ;do
动作块
done
- while read 变量名 ;do
-
示例
- 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
- while read line ;do
-
遍历文件,在遍历时,将整行的内容赋值给变量
-
-
-
until循环
-
用法
- until 条件表达式 ;do
循环体
done
- until 条件表达式 ;do
-
until与while相反
- while:当条件为真,执行循环体
- until:当条件为真,退出循环
-
-
循环控制语句
-
continue
-
作用
- 退出本次循环,直接进入下一次循环
- 意味着本次循环体中continue以下的语句将被跳过
- 变量的更新放在continue前面,否则会进入死循环
-
示例
- n=0
while :;do #恒为真
let n++
[ $n -eq 5 ] && continue
echo $n
[ $n -eq 10 ] && break
done
- n=0
-
-
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”
- tom[age]=20
-
-
-
应用
-
变量更新
- #!/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
-
统计数量
- #!/bin/bash
declare -A array
for i inawk -F: '{print $NF}' /etc/passwd
;do
let array[$i]++ #每遍历一个值,相同下标的元素值+1
done
- #!/bin/bash
-
for j in ${!array[@]};do
echo KaTeX parse error: Expected '}', got 'EOF' at end of input: {array[j]} $j
done
函数function
-
介绍
- 函数是完成某个特定功能的一段代码
- 函数不能独立运行, 需要使用时通过函数名调用函数
-
定义函数
- function_name() {
代码集
}
- 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”
}
- #!/bin/bash
-
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[@]}
- #!/bin/bash
-
用随机数做数组下标,重复则会覆盖该下标元素
-