上海网站建设免,湖南省建设厅假网站,足球排名最新排名世界,wordpress换主图之后图片不显示前言
编程语言分类
静态和动态语言#xff1a; 静态编译语言#xff1a;使用变量前#xff0c;先声明变量类型#xff0c;之后类型不能改变#xff0c;在编译时检查#xff0c;如Java语言、C语言 动态编译语言#xff1a;不事先声明#xff0c;可随时改变类型#…前言
编程语言分类
静态和动态语言 静态编译语言使用变量前先声明变量类型之后类型不能改变在编译时检查如Java语言、C语言 动态编译语言不事先声明可随时改变类型如Shell语言、python语言、javascript语言、php语言
强类型和弱类型语言 强类型语言不同类型数据操作必须经过强制转换成同一类型才能运算如javaC# 弱类型语言语言的运行时会隐式地做数据类型转换。无需指定类型默认均为字符型参与计算会自动进行隐式类型转换变量无需事先定义可直接调用。如Shell语言phpJavaScript
脚本检查工具
yum install -y epel-release
yum install -y ShellCheck
一、Shell脚本语言的基本结构
1、Shell脚本的用途 自动化常用命令 执行系统管理和故障排除 创建简单的应用程序 处理文本或文件
2、 Shell脚本基本结构
Shell脚本编程是基于过程式解释执行的语言
编程语言的基本结构 各种系统命令的组合 数据存储变量数组 表达式ab 控制语句if、case、for、while
shell脚本包含一些命令或声明并符合一定格式的文本文件
格式要求首行执行shebang机制
#声明后续语句是通过那种语言写的
#!/bin/bash
#!/usr/bin/python
#!/usr/bin/perl
3、 创建Shell脚本过程 使用vim创建文本文件第一行必须包括shell声明序列 #!/bin/bash 加执行权限给予执行权限在命令行上指定脚本的绝对或相对路径 [rootlocalhost ~]# chmod x shellScript/hello.sh 运行脚本直接运行解释器将脚本作为解释器程序的参数运行。 [rootlocalhost ~]# /root/shellScript/hello.sh
4、 脚本注释规范 第一行一般为调用使用的语言 程序名避免更改文件名为无法找到正确的文件 版本号 更改后的时间 作者相关信息 该程序的作用及注意事项 最后是各版本的更新简要说明
5、第一个脚本
[rootlocalhost ~]# cat shell/hostname.sh
#!/bin/bash
echo My hostname is hostname
echo Time is date %F %T
[rootlocalhost ~]# chmod x shell/hostname.sh
[rootlocalhost ~]# shell/hostname.sh
6、 执行脚本
1、增加执行权限执行脚本时会创建一个子shell不影响现有的shell环境
chmod x sh
./sh
/root/shellScript/sh
2、使用 . 或者source执行脚本时不会创建一个子shell会影响现有的shell环境
source sh
. sh
注意尽量不要使用该方式执行脚本
实例备份脚本
[rootlocalhost ~]# mkdir /backup/
[rootlocalhost ~]# vim shell/backup.sh
[rootlocalhost ~]# cat shell/backup.sh
#!/bin/bash
echo -e \033[1;32m\033[0m
sleep 2
cp -av /etc/ /backup/etcdate %F/
echo -e \033[1;32mBackup is finished\033[0m
[rootlocalhost ~]# chmod x shell/backup.sh
[rootlocalhost ~]# ./shell/backup.sh
Starting backup..
...
Backup is finished
7、脚本错误 语法错误会导致后续的命令不继续执行可以用bash -n shellname检查错误 命令错误后续的命令还会继续可以使用bash -x shellname检查 逻辑错误只能使用bash -x进行观察
二、Shell脚本语言的变量用法详解
1、变量
变量表示命名的内存空间将数据放在内存空间中通过变量名引用获取数据
2、 变量类型
变量类型 内置变量如PS1,PATH,UID,HOSTNAME,HISTSIZE 用户自定义变量 预定义变量 位置变量
不同的变量存放的数据不同决定了以下 数据存储方式 参与的计算 表示的数据范围
变量数据类型: 字符串 数值整型浮点型小数、bash不支持浮点数
3、 Shell中变量命名法则 不能使用程序中的保留字如iffor 只能使用数字字母及下划线且不能以数字开头 见名思意用英文名字并体现真正含义 统一命名规则驼峰命名法 全局变量名大写 局部变量小写 函数名小写
4、 变量定义和引用
变量的生效范围变量作用域 普通变量生效范围为当前shell进程对当前shell之外的其他shell进程包括当前shell的子shell进程均无效 环境变量生效范围为当前shell进程及其子进程 本地变量生效范围为当前shell进程中某代码片段通常指函数
变量赋值
namevalue
value可以是以下多种类型
直接字符串nameroot
变量引用name$USER
命令应用namecommand || name$(command)
通配符FILE/etc/* /*表示etc目录下所有的文件名*/
注意变量赋值是临时生效当退出终端后变量会自动删除无法持久保存。
变量引用
$name
${name}
弱引用和强引用 “$name”弱引用其中的变量引用会被替换成为变量值 ‘$name’强引用其中的变量引用不会被替换成变量值而保持原字符串
实例
[rootlocalhost ~]# nameMike
[rootlocalhost ~]# NAME$USER
[rootlocalhost ~]# hostnamehostname
[rootlocalhost ~]# echo My name is $name
My name is Mike
[rootlocalhost ~]# echo My name is $NAME
My name is root
[rootlocalhost ~]# echo My hostname is $hostname
My hostname is localhost.localdomain
[rootlocalhost ~]#
[rootlocalhost ~]# NUMseq 10
[rootlocalhost ~]# echo $NUM
1 2 3 4 5 6 7 8 9 10
[rootlocalhost ~]# echo $NUM
1
2
3
4
5
6
7
8
9
10
[rootlocalhost ~]#查看已定义的所有变量
[rootlocalhost ~]#set 删除变量 [rootlocalhost ~]#unset shellname1 shellname2
//实例
[rootlocalhost ~]# echo $name
Mike
[rootlocalhost ~]# unset name
[rootlocalhost ~]# echo $name
[rootlocalhost ~]# 实例{}的使用 [rootlocalhost ~]# NAMEmage
[rootlocalhost ~]# AGE20
[rootlocalhost ~]# echo $NAME
mage
[rootlocalhost ~]# echo $AGE
20
[rootlocalhost ~]# echo $NAME $AGE
mage 20
[rootlocalhost ~]# echo $NAME_$AGE
20
[rootlocalhost ~]# echo ${NAME}_$AGE
mage_20
[rootlocalhost ~]# 显示系统信息 [rootlocalhost ~]# vim shell/OS.sh
#!/bin/bash
RED\E[1;31m
GREEB\E[1;32m
END\E[0m
echo -e \E[1;32m----------Host systeminfo----------$END
echo -e HOSTNAME: $RED hostname$END
echo -e IPADDR: $RED ifconfig ens160 | grep -Eo ([0-9]{1,3}\.){3}[0-9]{1,3} | head -n1 $END
echo -e OSVERSION: $RED cat /etc/redhat-release$END
echo -e KERNEL: $RED uname -r$END
echo -e CPU: $RED lscpu | grep 型号名称 | tr -s |cut -d -f 2-5 $END
echo -e MEMORY: $RED free -h | grep Mem | tr -s |cut -d -f 4 $END
echo -e DISK: $RED lsblk | grep ^sda | tr -s | cut -d -f 4 $END
echo -e \E[1;32m---------- END ----------$END
[rootlocalhost ~]# chmod x shell/OS.sh
[rootlocalhost shellScript]# ./os.sh
----------Host systeminfo----------
HOSTNAME: localhost.localdomain
IPADDR: 19168.115.213
OSVERSION: CentOS Linux release 7.9.2009 (Core)
KERNEL: 3.10.0-1160.el7.x86_64
CPU: 11th Gen Intel(R) Core(TM)
MEMORY: 1.0G
DISK: 200G
---------- END ---------- 利用变量实现动态命令 [rootlocalhost ~]# CMDhostname
[rootlocalhost ~]# $CMD
localhost.localdomain
[rootlocalhost ~]#
5、 环境变量
环境变量 可以使子进程(包括孙子进程)继承父进程的变量但是无法让父进程使用子进程的变量。 一旦子进程修改了从父进程继承的变量将会传递新的值给孙子进程 一般只在配置文件中使用在脚本中较少使用 课程引入普通变量生效的范围与环境变量生效的范围 [rootlocalhost ~]# vim shell/father.sh
#!/bin/bash
NAMEfather
echo father.sh:NAME$NAME
echo fatther is PID$BASHPID
shell/son.sh
[rootlocalhost ~]#vim shell/son.sh
#!/bin/bash
echo son.sh:NAME$NAME
NAMEson
echo son.sh:NAME$NAME
echo son.sh PID is $BASHPID
echo son.sh father pid is $PPID
sleep 100
[rootlocalhost ~]#chmod -R x shell/*
[rootlocalhost ~]# ./shell/father.sh
father.sh:NAMEfather
fatther is PID12053
son.sh:NAME
son.sh:NAMEson
son.sh PID is 12054
son.sh father pid is 12053
#子进程无法使用父进程的变量需要自己赋值
变量声明和赋值
export nameVALUE
declare -x name VALUE
#或者先赋值再声明~
value可以是以下多种类型
直接字符串nameroot
变量引用name$USER
命令应用namecommand || name$(command)
通配符FILE/etc/* /*表示etc目录下所有的文件名*/
declare命令详解了解
declare 为 shell 指令在第一种语法中可用来声明变量并设置变量的属性([rix]即为变量的属性在第二种语法中可用来显示 shell 函数。若不加上任何参数则会显示全部的 shell 变量与函数(与执行 set 指令的效果相同)
语法
declare [/-][rxi][变量名称设置值] 或 declare -f
参数说明 /- -“可用来指定变量的属性”则是取消变量所设的属性。 -f 仅显示函数 r 将变量声明为只读变量。注意一旦设置为只读变量既不能修改变量的值也不能删除变量甚至不能通过r取消只 读属性 x 指定的变量会成为环境变量可供shell以外的程序来使用 i 将变量声明为整数型integer p 显示指定变量的被声明类型。
实例
1.声明整数型变量
#!/bin/bash
declare -i ab //声明整数型变量
ab56 //改变变量内容
echo $ab //显示变量内容
---
56
改变变量属性
#!/bin/bash
#声明整数型变量
declare -i ef
ef1
echo $ef
#变量赋值赋予文本值
efwer
echo $ef
#取消变量属性
declare i ef
efwer
echo $ef
3.设置变量只读
#!/bin/bash
declare -r ab #设置变量为只读
ab88 #改变变量内容
echo $ab #显示变量内容
---
declare.sh:行3: ab: 只读变量
4.声明数组变量
#!/bin/bash
#声明数组变量
declare -a cd
cd[0]a
cd[1]b
cd[2]c
#输出数组的指定内容
echo ${cd[1]}
#显示整个数组变量内容
echo ${cd[]}
5.显示函数
#!/bin/bash
#声明函数
declare -f
function command_not_found_handle(){if [ -x /usr/lib/command_not_found_handle ];then/usr/bin/python /usr/lib/command_not_found_handle -- $1;return $?;elseif [ -x /usr/share/command_not_found_handle ];then/usr/bin/python /usr/share/command_not_found_handle --$1;return $?;elsereturn 127;fi;fi;
}
变量引用
$name
${name} 完善课程导入 [rootlocalhost ~]# vim shell/father.sh
#!/bin/bash
NAMEfather
export NAME
echo father.sh:NAME$NAME
echo fatther is PID$BASHPID
shell/son.sh
[rootlocalhost ~]#vim shell/son.sh
#!/bin/bash
echo son.sh:NAME$NAME
NAMEson
echo son.sh:NAME$NAME
echo son.sh PID is $BASHPID
echo son.sh father pid is $PPID
sleep 100
[rootlocalhost ~]#chmod -R x shell/*
[rootlocalhost ~]# ./shell/father.sh
father.sh:NAMEfather
fatther is PID12053
son.sh:NAMEfather
son.sh:NAMEson
son.sh PID is 12054
son.sh father pid is 12053
[rootlocalhost ~]# ./shell/father.sh
father.sh:NAMEfather
fatther is PID12142
son.sh:NAMEfather
son.sh:NAMEson
son.sh PID is 12143
son.sh father pid is 12142#父进程定义了一个环境变量在子进程上可以进行调用#父进程无法使用子进程的变量#子进程自己定义了一个同名变量就覆盖环境变量
显示所有环境变量
[rootlocalhost ~]# env
[rootlocalhost ~]# printenv
[rootlocalhost ~]# export
[rootlocalhost ~]# declare -x
删除变量
[rootlocalhost ~]#unset shellname1 shellname2
Bash内建的环境变量
PATH
SHELL
USER
UID
PWD
SHLVL #shell的嵌套层数即深度
LANG
MAIL
HOSTNAME
HISTSIZE
_ #下划线表示前一命令的最后一个参数
6、只读变量
只读变量只能声明定义但后续不能修改和删除
声明只读变量
readonly name
declare -r name
查看只读变量
readonly [-p]
declare -r
7、位置变量
位置变量在Bash Shell中内置的变量在脚本代码中调用命令行传递给脚本的参数
$1,$2,... 对应第一个第二个等参数shift[n]换位置最多9个
#预定义变量
$0 命令本身包括路径
$* 传递给脚本的所有参数全部参数合成一个字符串
$ 传递给脚本的所有参数每个参数为独立字符串
$# 传递给脚本的参数的个数
$? 上个命令的退出状态,或函数的返回值
$$ 当前shell进程ID。对于Shell脚本,就是这些脚本所在的进程ID
注意$,$*只有被双引号括起来的时候才会有差异
清空所有位置变量
set --
//写在脚本内部 实例演示1 [rootlocalhost ~]# vim shell/ARG.sh
#!/bin/bash
echo 1st arg is $1
echo 2st arg is $2
echo 3st arg is $3
echo 4st arg is $4
echo The number of are is $#
echo All args are $*
echo All args are $
echo The scriptname is basename $0
[rootlocalhost ~]# chmod x shell/ARG.sh
[rootlocalhost ~]# shell/ARG.sh {1..10}
1st arg is 1
2st arg is 2
3st arg is 3
4st arg is 4
The number of are is 10
All args are 1 2 3 4 5 6 7 8 9 10
All args are 1 2 3 4 5 6 7 8 9 10
The scriptname is ARG.sh
[rootlocalhost ~]# 实例演示2编写一个移动文件脚本 [rootlocalhost ~]# vim shell/move.sh
#!/bin/bash
WANGING_COLORecho -e \E[1;31m
END\E[0m
DIR/tmp/date %F_%H-%M-%S
mkdir $DIR
mv $* $DIR
${WANGING_COLOR} MOVE $* to $DIR $END
[rootlocalhost ~]# chmod x shell/move.sh
[rootlocalhost ~]# touch {a,b,c}
[rootlocalhost ~]# ls
a anaconda-ks.cfg b c shell
[rootlocalhost ~]# shell/move.sh a b cMOVE a b c to /tmp/2022-08-16_10-07-55
[rootlocalhost ~]# tree /tmp/
/tmp/
└── 2022-08-16_10-07-55├── a├── b└── c
1 directory, 3 files
[rootlocalhost ~]#
8、 退出状态码变量
进程执行后将使用变量 ? 保存状态码的相关数字不同的值反应成功与失败 ?保存状态码的相关数字不同的值反应成功与失败 ?保存状态码的相关数字不同的值反应成功与失败的取值范围为[0,255]
$?的值为0 代表成功
$?的值不为0 代表失败
用户可以在脚本中使用以下命令自定义退出状态码
exit [n] 实例: [rootlocalhost ~]# ping -c 2 www.baidu.com /dev/null
[rootlocalhost ~]# echo $?
0
[rootlocalhost ~]# cmd
-bash: cmd: 未找到命令
[rootlocalhost ~]# echo $?
127
[rootlocalhost ~]#
注意 脚本中一旦遇到了exit命令脚本会立即终止终止退出状态取决于exit命令后面的数字 如果未给脚本指定退出状态码整个脚本的退出状态码取决于脚本中执行的最后一条命令的状态码 实例1$?获取上一个命令的退出状态 #!/bin/bash
if [ $1100 ];thenexit 0 #参数正确,退出状态为0
elseexit 1 #参数错误,退出状态为1
fi
exit表示退出当前 Shell 进程我们必须在新进程中运行 test.sh否则当前 Shell 会话终端窗口会被关闭我们就无法取得它的退出状态了
[rootlocalhost re_study]# bash test.sh 100
[rootlocalhost re_study]# echo $?
0
[rootlocalhost re_study]# bash test.sh 99
[rootlocalhost re_study]# echo $?
1
[rootlocalhost re_study]# 实例2$?获取函数的返回值 #!/bin/bash
#得到两个数相加的和
function add(){return expr $1 $2
}
add 23 50 #调用函数
echo $? #获取函数返回值
# 运行结果
[rootlocalhost re_study]# bash test.sh
73
9、 展开命令行
9.1展开命令执行顺序
把命令行分成单个命令词
展开别名
展开大括号的声明{}
展开波浪符声明~
命令替换$()和
再次把命令行分成命令词
展开文件通配(*,?,[abc]等)
准备I/O重导向(,)
运行命令
9.2 防止扩展
反斜线(\)会使随后的字符按原意解释 实例 [rootlocalhost ~]# echo Your cost: \$5.00
Your cost: $5.00
[rootlocalhost ~]#
9.3 加引号来防止扩展
单引号( )防止所有扩展
双引号( )可防止扩展但是以下清空例外$(美元符号)
9.4 变量扩展
:反引号命令替换
\:反斜线禁止单个字符扩展
叹号历史命令替换
10、 脚本安全和set暂时不用
set命令可以用来定制shell环境
10.1 $-变量 hhashell打开选项后Shell会将命令所在的路径hash下来避免每次都要查询。通过set h将h选项关闭.默认开启 iinteractive-comments包含这个选项说明当前的shell是一个交互式的shell。所谓的交互式shell在脚本中i选项是关闭的 mmonitor打开监控模式就可以通过Job control来控制进程的停止继续后台或者前台执行等 Bbraccexpand大括号扩展 HhistoryH选项打开可以展开历史列表中的命令可以通过!来完成例如!!返回最近的一个历史命令!n返回第n个历史命令 实例 [rootlocalhost ~]# echo $-
himBHs
[rootlocalhost ~]# hash
命中 命令1 /usr/sbin/ping
[rootlocalhost ~]# set h
[rootlocalhost ~]# echo $-
imBHs
[rootlocalhost ~]# hash
-bash: hash: 已禁用哈希
[rootlocalhost ~]#
[rootlocalhost ~]# echo {1..10}
1 2 3 4 5 6 7 8 9 10
[rootlocalhost ~]# set B
[rootlocalhost ~]# echo {1..10}
{1..10}
[rootlocalhost ~]#
[rootlocalhost ~]# set H
[rootlocalhost ~]# history !!
-bash: history: !!: 需要数字参数
[rootlocalhost ~]# history !3
-bash: history: !3: 需要数字参数
[rootlocalhost ~]# set -H
[rootlocalhost ~]# history !!
history set -H
-bash: history: set: 需要数字参数
[rootlocalhost ~]# history !3
history ifconfg
-bash: history: ifconfg: 需要数字参数
[rootlocalhost ~]#
10.2 set命令实现脚本安全 -u在扩展一个没有设置的变量时显示错误信息等同于set -o nounset -e如果一个命令返回一个非0退出的状态值(失败)就退出等同于set -o errexit -ooption 显示打开或关闭选项 显示选项set -o 打开选项set -o 选项 关闭选项set o 选项 -x当执行命令时打印命令及其参数类似bash -x 实例 [rootlocalhost ~]# set -o
allexport off
braceexpand off
emacs on
errexit off
errtrace off
functrace off
hashall on
histexpand on
history on
ignoreeof off
interactive-comments on
keyword off
monitor on
noclobber off
noexec off
noglob off
nolog off
notify off
nounset off
onecmd off
physical off
pipefail off
posix off
privileged off
verbose off
vi off
xtrace off
[rootlocalhost ~]# vim shell/error.sh
#!/bin/bash
echo Hello World
sssss
echo Hello Linux
[rootlocalhost ~]# chmod x shell/error.sh
[rootlocalhost ~]# shell/error.sh
Hello World
shell/error.sh:行3: sssss: 未找到命令
Hello Linux
[rootlocalhost ~]# vim shell/error.sh
#!/bin/bash
set -e
echo Hello World
sssss
echo Hello Linux
[rootlocalhost ~]# shell/error.sh
Hello World
shell/error.sh:行4: sssss: 未找到命令
[rootlocalhost ~]#
三、 Shell字符串详解
字符串(String)就是一系列字符的组合。字符串是Shell编程中最常用的数据类型之一
字符串可以由单引号包围也可以由包围也可以不用引号三种方式的区别 由单引号 包围的字符串 任何字符都会原样输出在其中使用变量是无效的 字符串中不能出现单引号即使对单引号进行转义也不行 由双引号 包围的字符串 如果其中包含了某个变量那么该变量就会被解析(得到该变量的值)而不是原样输出 字符串中可以出现双引号只要进行转义就行 不被引号包围的字符串 不被引号包围的字符串中出现变量也会被解析这一点和双引号包围的字符串一样 字符串中不能出现空格否则空格后面的字符串会作为其他变量或者命令解析 通过代码演示一下三种形式的区别 #!/bin/bash
n74
str1c.biancheng.net$n
str2shell \Script\ $n
str3C语言中文网 $n
echo $str1
echo $str2
echo $str3
# 运行结果
c.biancheng.net74
shell Script 74
C语言中文网 $n
str1 中包含了$n它被解析为变量 n 的引用。$n后边有空格紧随空格的是 str2Shell 将 str2 解释为一个新的变量名而不是作为字符串 str1 的一部分
str2 中包含了引号但是被转义了由反斜杠\开头的表示转义字符。str2 中也包含了$n它也被解析为变量 n 的引用
str3 中也包含了$n但是仅仅是作为普通字符并没有解析为变量 n 的引用
获取字符串长度
在Shell中获取字符串长度很简单具体方法如下:
${#string_name}
string_name表示字符串名字
1、Shell字符串拼接
在脚本语言中字符串的拼接(也称为字符串连接或者字符串合并)往往都非常简单例如 在PHP中使用.即可连接两个字符串 在JavaScript中使用即可将两个字符串合并为一个
然而在Shell中你不需要使用任何运算符将两个字符串并排放在一起就能实现拼接
#!/bin/bash
nameshell
urlhttp://c.biancheng.net/shell/
str1$name$url #中间不能有空格
str1$name:$url
str2$name $url #如果被双引号包围,那么中间可以有空格,也可以出现别的字符串
str3$name:$url
str4${name}Script:${url}Index.html #在变量后加上字符串,需要给变量名加上大括号
2、Shell字符串截取
Shell截取字符串通常有两种方式从指定位置开始截取和从指定字符(子字符串)开始截取
从指定位置开始截取
这种方式需要两个参数除了指定起始位置还需要截取长度才能最终确定要截取的字符串
既然需要指定起始位置那么就要涉及到计数方向的问题到底是从字符串左边开始计数还是从字符串右边开始计数答案是:Shell同时支持两种计数方式
1.从字符串左边开始计数
如果想从字符串的左边开始计数那么截取字符串的具体格式如下
${string:start:length}
其中,Sting是要截取的字符串,start是起始位置(从左边开始,从0开始计数),length是要截取的长度(省略的话表示直到字符串的末尾)
例如
urlc.biancheng.net
echo ${url:2:9}
结果为biancheng
urlc.biancheng.net
echo ${url:2} #省略length,截取到字符串末尾
结果为biancheng.net
2.从右边开始计数
如果想从字符串的右边开始计数那么截取字符串的具体格式如下
${string:0-start:length}
同第 1) 种格式相比第 2) 种格式仅仅多了0-这是固定的写法专门用来表示从字符串右边开始计数。
这里需要强调两点
从左边开始计数时起始数字是 0这符合程序员思维
从右边开始计数时起始数字是 1这符合常人思维
计数方向不同起始数字也不同。
不管从哪边开始计数截取方向都是从左到右。
例如
urlc.biancheng.net
echo ${url:0-13:9}
结果为biancheng 从右边数b是第13个字符
urlc.biancheng.net
echo ${url:0-13} #省略length,直接截取到字符串末尾
结果为:biancheng.net
从指定字符子字符串开始截取
这种截取方式无法指定字符串长度只能从指定字符(子字符串)截取到字符串末尾。Shell可以截取指定字符(子字符串)右边的所有字符也可以截取左边的所有字符
1)使用#号截取右边字符
使用#号可以截取指定字符(或子字符串)右边的所有字符具体格式如下
${string#*chars}
#其中string 表示要截取的字符chars 是指定的字符或者子字符串*是通配符的一种表示任意长度的字符串。*chars连起来使用的意思是忽略左边的所有字符直到遇见 charschars 不会被截取
例如
urlhttp://c.biancheng.net/index.html
echo ${url#*:}
结果为//c.biancheng.net/index.html
echo ${url#*p:}
echo ${url#*ttp:}
如果不需要忽略chars左边的字符,那么也可以不写*
urlhttp://c.biancheng.net/index.html
echo ${url#http://}
结果为c.biancheng.net/index.html
注意以上写法遇到第一个匹配的字符(子字符串)就结束了
urlhttp://c.biancheng.net/index.html
echo ${url#*/}
结果为/c.biancheng.net/index.html。url 字符串中有三个/输出结果表明Shell 遇到第一个/就匹配结束了
使用##可以直到最后一个指定字符(子字符串)再匹配结束
${string##*chars}
例如
#!/bin/bash
urlhttp://c.biancheng.net/index.html
echo ${url#*/}
# 结果为/c.biancheng.net/index.html
echo ${url##*/}
# 结果为index.html
str-----aaaa
echo ${str#*aa}
# 结果为aa
echo ${str##*aa}
# 结果为
2)使用%截取左边字符
使用%号可以截取指定字符(或者子字符串)左边的所有字符
${string%chars*}
请注意*的位置因为要截取 chars 左边的字符而忽略 chars 右边的字符所以*应该位于 chars 的右侧。其他方面%和#的用法相同
#!/bin/bash
urlhttp://c.biancheng.net/index.html
echo ${url%/*} #结果为 http://c.biancheng.net
echo ${url%%/*} #结果为 http:
str---aaaa
echo ${str%aa*} #结果为 ---aa
echo ${str%%aa*} #结果为 ---
3、汇总
格式说明${string:start :length}从string字符串的左边第start个字符开始向右截取length个字符。${string:start}从string字符串的左边第start个字符开始截取直到最后。${string:0-start:length}从string字符串的右边第start个字符开始向右截取length个字符。${string:0-start}从string字符串的右边第start个字符开始截取直到最后。${string#*chars}从string字符串第一次出现chars的位置开始截取chars右边的所有字符。${string##*chars}从string字符串最后一次出现chars的位置开始截取chars右边的所有字符。${string%chars*}从string字符串第一次出现chars的位置开始截取chars左边的所有字符。${string%%chars*}从string字符串最后一次出现chars的位置开始截取chars左边的所有字符。
4、Shell的格式化输出printf
4.1、语法格式:
printf 指定的格式 文本1 文本2 .....
4.2、常用格式替换符
替换符功能%s字符串%f浮点格式保留小数点位数%.nfn为数字%b相对应的参数中包括转义字符时可以使用此替换符进行替换对应的转义字符会被转义%cASCII字符即显示对应参数的第一个字符%d,%i十进制整数%o八进制值%u不带正负号的十进制值%x十六进制值a-f%X十六进制值A-F%%表示%本身
说明%s中的数字代表此替换符中的输出字符宽度不足补空格默认是右对齐%-10s表示10个字符宽-表示左对齐
4.3、常用转义字符
转义符功能\a警告字符通常为ASCII的BEL字符\b后退\f换页\n换行\r回车\t水平制表符\v垂直制表符\\表示\本身 实例 [rootlocalhost ~]# printf %s\n 1 2 3 4
1
2
3
4
[rootlocalhost ~]# printf %f\n 1 2 3 4
1.000000
2.000000
3.000000
4.000000
[rootlocalhost ~]# printf %.2f\n 1 2 3 4 #.2f表示保留两位小数
1.00
2.00
3.00
4.00
[rootlocalhost ~]# printf (%s) 1 2 3 4;echo
(1)(2)(3)(4)
[rootlocalhost ~]# printf (%s) 1 2 3 4;echo (1) (2) (3) (4)
[rootlocalhost ~]# printf (%s) (%s)\n 1 2 3 4;echo (1) (2)(3) (4)
[rootlocalhost ~]# printf %s %s\n 1 2 3 4;echo 1 23 4
[rootlocalhost ~]# printf %s %s %s\n 1 2 3 4
1 2 3
4
[rootlocalhost ~]#
#%-10s表示宽度10个字符左对齐
[rootlocalhost ~]# printf %-10s %-10s %-4s %s \n 姓名 性别 年龄 体重 小明 男性 20岁 70KG 小红 女性 18岁 50KG
姓名 性别 年龄 体重
小明 男性 20岁 70KG
小红 女性 18岁 50KG
[rootlocalhost ~]#
#将十进制的1000转换为16进制数
[rootlocalhost ~]# printf %X\n 1000
3E8
[rootlocalhost ~]# printf %x\n 1000
3e8
[rootlocalhost ~]#
#将十六进制的C转换为十进制
[rootlocalhost ~]# printf %d\n 0xc
12
[rootlocalhost ~]#
[rootlocalhost ~]# varwelcome to study;printf \033[31m%s\033[0m\n $var
welcome
to
study
[rootlocalhost ~]# varwelcome to study;printf \033[31m%s\033[0m\n $var
welcome to study
[rootlocalhost ~]#
四、Shell脚本语言的运算
4.1 算数运算
shell支持算术运算但只支持整数不支持小数
4.2 Bash中的算术运算
-- 加法运算
-- - 减法运算
-- * 乘法运算
-- / 除法运算
-- % 取模即取余数
-- ** 乘方
#乘法符号在有些场景需要转义
4.2 实现算术运算
1. let var算术表达式
2. var$[算术表达式]
3. var$((算术表达式))
4. var$(expr arg1 arg2 arg3 ...)
5. declare -i var 数值
6. echo 算术表达式 | bc (支持浮点数) 实例使用bc计算小数和declare -i计算 [rootlocalhost ~]# echo scale3;20/3|bc
6.666
[rootlocalhost ~]# echo scale3;2/3|bc
.666
[rootlocalhost ~]# i20
[rootlocalhost ~]# j20
[rootlocalhost ~]# declare -i sumi*j
[rootlocalhost ~]# echo $sum
400
[rootlocalhost ~]#
内建的随机数生成器变量
$RANDOM 取值范围0-32767 实例生成0-49之间的随机数 [rootlocalhost ~]# echo $[$[$RANDOM%50]1]
40
[rootlocalhost ~]# echo $[$RANDOM%50]
44
[rootlocalhost ~]# echo $[$[$RANDOM%50]1] #生成1~50之间的随机数
[rootlocalhost ~]# echo $[RANDOM % 100 1] 实例生成随机颜色字符串 [rootlocalhost ~]# echo -e \033[1;$[RANDOM%731]mStudy\033[0m
Study
[rootlocalhost ~]# echo -e \033[1;$[RANDOM%731]mStudy\033[0m
Study
[rootlocalhost ~]#
4.3 增强型赋值 i10 i110
-
i-j ii-j
*
/
%i,1 ii1 自增
--
i--,--i ii-1 自减
格式
let varOPERvalue 实例自增自减 [rootlocalhost ~]# let var1
[rootlocalhost ~]# echo $var
1
[rootlocalhost ~]# let var
[rootlocalhost ~]# echo $var
2
[rootlocalhost ~]# let var-1
[rootlocalhost ~]# echo $var
1
[rootlocalhost ~]# let var--
[rootlocalhost ~]# echo $var
0
[rootlocalhost ~]#
[rootlocalhost ~]# unset i j ;i1;let ji;echo i$i,j$j
i2,j1
[rootlocalhost ~]# unset i j ;i1;let ji;echo i$i,j$j
i2,j2
[rootlocalhost ~]#
# i 与 i的区别:
i 先赋值再运算
i 先运算再赋值
实例鸡兔同笼问题 [rootlocalhost ~]# vim shell/chicken.sh
#!/bin/bash
HEAD35
FOOT94
RABBIT$(((FOOT-HEAD-HEAD)/2))
CHOOK$[35-RABBIT]
echo 兔子的数量为$RABBIT
echo 鸡的数量为: $CHOOK[rootlocalhost ~]# chmod x shell/chicken.sh
[rootlocalhost ~]# shell/chicken.sh
兔子的数量为:12
鸡的数量为:23
[rootlocalhost ~]#
# 在脚本中写入变量让用户在命令行写入需要计算的数值
[rootlocalhost ~]# vim shell/chicken.sh
#!/bin/bash
HEAD$1
FOOT$2
RABBIT$(((FOOT-HEAD-HEAD)/2))
CHOOK$[35-RABBIT]
echo 兔子的数量为$RABBIT
echo 鸡的数量为: $CHOOK[rootansible-salve1 ~]# ./chicken.sh 30 80
兔子的数量为10
鸡的数量为: 25
[rootansible-salve1 ~]# 面试题计算出所有人的年龄总和 [rootansible-salve1 shell]# vim nianling.txt
[rootansible-salve1 shell]# cat nianling.txt
a20
b18
c22
[rootansible-salve1 shell]# cut -d -f2 nianling.txt
20
18
22
[rootansible-salve1 shell]# cut -d -f2 nianling.txt | tr \n | grep -Eo .*[0-9] | bc
60
[rootansible-salve1 shell]# grep -Eo [0-9] nianling.txt
20
18
22
[rootansible-salve1 shell]# grep -Eo [0-9] nianling.txt | tr \n | grep -Eo .*[0-9] | bc
60
[rootansible-salve1 shell]#
4.2 逻辑运算了解不用掌握 True用数字表示1False用数字表示0 与 1 与 1 1
1 与 0 0
0 与 1 0
0 与 0 0 或| 1 或 1 1
1 或 0 1
0 或 1 1
0 或 0 0 非 !1 0 !TrueFalse
!0 1 !FalseTrue 异或^ #异或的两个值相同为假不同为真
1 ^ 1 0
1 ^ 0 1
0 ^ 1 1
0 ^ 0 0
4.3 短路运算不用了解 短路与 CMD1 短路与 CMD2
--第一个CMD1结果为0假总的结果必定为0所以不需要执行CMD2
--第二个CMD1结果为1真第二个CMD2必须要参与计算才能得到最终的结果 短路或 CMD1 短路或 CMD2
--第一个CMD1结果为1真总的结果必定为1因此不需要执行CMD2
--第一个CMD1结果为0假第二个CMD2必须要参与运算才能得到最终的结果
4.4 条件测试命令
条件测试判断某需求是否满足需要由测试机制来实现专用的测试表达式需要由测试命令辅助完成测试过程实现评估布尔声明以便在条件性环境下进行执行。 若真则状态码变量$?返回0 若假则状态码变量$?返回1 扩展: [ ] 与 [[ ]] 的区别 区别1
[ ]是符合POSIX标准的测试语句,兼容性强,几乎可以运行在所有的Shell解释器中
[[ ]]仅可运行在特定的几个Shell解释器中(如Bash)
区别2可以在[[ ]]中使用ASCII码顺序进行排序,而[]不支持
区别3:
在[ ]中使用-a 和 -o 表示逻辑与和逻辑或,[[ ]]使用 和 || 表示,[[ ]]不支持-a
区别4
在[ ]中是字符匹配,在[[ ]]中是模式匹配
区别5
[ ]不支持正则匹配,[[ ]]支持用~进行正则匹配
区别6
[ ]仅在部分Shell中支持用()进行分组,[[ ]]均支持
区别7
在[ ]中如果变量没有定义,那么需要用双引号引起来,在[[ ]]中不需要
4.4.1 条件测试命令及其语法 语法1test 测试表达式 说明test命令和测试表达式之间至少有一个空格 # 在shell中大于用 -gt 表示小于用 -lt 表示大于或等于用 -ge 表示小于或等于用 -le表示 不相等用-ne 表示
[rootansible-salve1 ~]# test 1 -lt 2
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]# test 2 -lt 1
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# 语法2[测试表达式] 说明该方法和test命令的用法一样[]的两边和内容之间至少有一个空格 [rootansible-salve1 ~]# [ 1 -gt 3 ]
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# [ 1 -lt 3 ]
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]# 语法3[[ 测试表达式 ]] 说明比test和[]更新的语法格式。[[]]的边界和内容之间至少有一个空格。[[]]中可以使用通配符等进行模式匹配 [rootansible-salve1 ~]# [[ 1 3 ]]
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# [[ 1 3 ]]
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]# 语法4((测试表达式)) 说明一般用于if语句里双小括号两端不需要有空格测试对象只能是整数 [rootansible-salve1 ~]# ((12))
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# ((12))
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]#
4.4.2 变量测试
语法规则-v VAR 变量var是否被定义 示例判断NAME变量是否被定义 [rootansible-salve1 shell]# [[ -v NAME ]]
[rootansible-salve1 shell]# echo $?
1
[rootansible-salve1 shell]# NAME1
[rootansible-salve1 shell]# [[ -v NAME ]]
[rootansible-salve1 shell]# echo $?
0
[rootansible-salve1 shell]#
语法规则 -R VAR 变量VAR是否被引用 示例判断NAME变量是否被引用 [rootansible-salve1 shell]# NAME10
[rootansible-salve1 shell]# test -v NAME
[rootansible-salve1 shell]# echo $?
0
[rootansible-salve1 shell]# test -R NAME
[rootansible-salve1 shell]# echo $?
1
[rootansible-salve1 shell]#
4.4.3 文件测试表达式
常用的文件测试操作符说明-a/-e 文件文件是否存在-b 文件文件是否存在且为块文件如果文件存在且是一个块文件则结果为0-c 文件文件是否存在且为字符文件如果文件存在且是一个字符文件则结果为0-L 文件 或 -h 文件文件存在且为链接文件则为真-d 文件文件存在且为目录则为真即测试表达式成立-f 文件文件存在且为普通文件则为真即测试表达式成立-s 文件文件存在且文件大小不为0则为真-S 文件文件是否存在且为套接字文件-p 文件文件是否存在且为管道文件-u 文件文件是否存在且拥有suid的权限如果设置了suid则结果为0-g 文件文件是否存在且拥有sgid的权限-r 文件文件存在且可读为真-w 文件文件存在且可写为真-x 文件文件存在且可执行则为真-t fdfd 文件描述符是否在某终端已经被打开-N 文件文件自从上一次读取之后是否被修改过-O 文件当前有效用户是否为文件属主-G 文件当前有效用户是否为文件属组f1 -ef f2文件f1是否是文件f2的硬链接f1 -nt f2nt为newerthan文件f1比文件f2新则为真根据文件的修改时间来计算f1 -ot f2ot为olderthan文件f1比文件f2旧则为真根据文件的修改时间来计算 测试文件 [rootansible-salve1 ~]# test -a test.txt
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# test -d shell
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]# touch test.txt
[rootansible-salve1 ~]# test -w test.txt echo true
true
[rootansible-salve1 ~]# test -r test.txt echo true
true
[rootansible-salve1 ~]# test -x test.txt echo true
[rootansible-salve1 ~]#
4.4.4 字符串测试表达式
常用字符串测试操作符说明-n ”字符串“若字符串的长度不为0则为真即测试表达式成立n可以理解为nozero-z ”字符串“若字符串的长度为0则为真z可以理解为zeroAscii码是否大于Ascii码“字符串1” ”字符串2“若字符串1长度等于字符串2长度则为真“字符串1” ! ”字符串2“若字符串1长度不等于字符串2长度则为真“字符串1” ~ “字符串2”左侧字符串是否能被右侧的PATTERN所匹配。注意此表达式用于[[ ]]中扩展的正则表达式 测试字符串 [rootansible-salve1 ~]# var_testMike
[rootansible-salve1 ~]# echo $var_test
Mike
[rootansible-salve1 ~]# [[ -n var_test ]] echo True
True
# 通配符
[rootansible-salve1 ~]# FILEtest.log
[rootansible-salve1 ~]# [[ $FILE *.log ]] echo True
True
[rootansible-salve1 ~]# FILEtest.txt
[rootansible-salve1 ~]# [[ $FILE *.log ]] echo True
[rootansible-salve1 ~]# [[ $FILE ! *.log ]] echo True
True
[rootansible-salve1 ~]#
# 扩展的正则表达式
[rootansible-salve1 ~]# FILEtest.log
[rootansible-salve1 ~]# [[ $FILE ~ \.log$ ]] echo True
True
[rootansible-salve1 ~]# N100
[rootansible-salve1 ~]# [[ $N ~ ^[0-9]$ ]] echo True
True
[rootansible-salve1 ~]# NA10
[rootansible-salve1 ~]# [[ $N ~ ^[0-9]$ ]] echo True
[rootansible-salve1 ~]# IP1.2.3.4
[rootansible-salve1 ~]# [[ $IP ~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]#
# 使用正则表达式判断IP是否合法
[rootansible-salve1 ~]# IP1.2.3.333
[rootansible-salve1 ~]# [[ $IP ~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# IP255.255.255.255
[rootansible-salve1 ~]# [[ $IP ~ ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$ ]]
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]#
4.4.5 整数测试表达式
在[ ] 或 test中使用的比较符号在(()) 或 [[ ]]中使用的比较符号不用这个做数字比较说明-eq\ 或 相等equal-ne!不相等not equal-gt大于greater than-ge 大于等于greater equal-lt小于less than-le 小于等于less equal
4.4.6 逻辑操作符
在[ ] 中使用的操作符在test, [[ ]] , (( ))中使用的逻辑操作符说明-aand,与两边都为真则结果为真-o||or或有真则真同假则假not非两端相反则结果相反 示例 [rootansible-salve1 ~]# var_test1
[rootansible-salve1 ~]# var_t2
[rootansible-salve1 ~]# [ $var_test -lt 0 -a $var_t -gt 0 ]
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# [ $var_test -lt 0 -o $var_t -gt 0 ]
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]#
4.5 关于与 { } 和 { }都可以将多个命令组合再一次批量执行{ } 里的内容需要与两侧用空格隔开并在命令结尾加上; ( )会开启子shell并且list中变量赋值及内部命令执行后将不再影响后续的环境 [rootansible-salve1 ~]# namemage;(echo $name;namewang;echo $name);echo $name
mage
wang
mage
[rootansible-salve1 ~]# (umask 444;umask);umask
0444
0022
[rootansible-salve1 ~]# (umask 444;touch 1.txt);umask
0022
[rootansible-salve1 ~]# ll 1.txt
--w--w--w- 1 root root 0 11月 13 22:12 1.txt
[rootansible-salve1 ~]# echo $BASHPID
1418
[rootansible-salve1 ~]# (echo $BASHPID; sleep 3)
1501
{ } 不会开启子shell在当前shell中运行会影响当前shell环境 [rootansible-salve1 ~]# namemage;{ echo $name;namewang;echo $name; };echo $name
mage
wang
wang
[rootansible-salve1 ~]# { umask 444;touch 1.txt; };umask
0444
[rootansible-salve1 ~]# umask
0444
[rootansible-salve1 ~]# ll 1.txt
--w--w--w- 1 root root 0 11月 13 22:23 1.txt
[rootansible-salve1 ~]# echo $BASHPID
1418
[rootansible-salve1 ~]# { echo $BASHPID; sleep 3; }
1418
[rootansible-salve1 ~]#
4.6 组合测试条件
4.6.1 第一种方式[ ]
[ EXPRESSION1 -a EXPRESSION2] 并且 条件1与条件2都为真结果才为真
[ EXPRESSION1 -O EXPRESSION2] 或 条件1与条件2只要有一个为真结果就为真
[ !EXPRESSION1 ] 取反
说明-a 和 -o 需要使用测试命令执行[[ ]] 不支持 示例 [rootansible-salve1 ~]# ll 1.txt
--w--w--w- 1 root root 0 11月 13 22:23 1.txt
[rootansible-salve1 ~]# FILE/root/1.txt
[rootansible-salve1 ~]# [ -f $FILE -a -x $FILE ]
[rootansible-salve1 ~]# echo $?
1
[rootansible-salve1 ~]# chmod x /root/1.txt
[rootansible-salve1 ~]# [ -f $FILE -a -x $FILE ]
[rootansible-salve1 ~]# echo $?
0
[rootansible-salve1 ~]#
4.6.2 第二种方式[[ ]]
COMMAND1 COMMAND2 #并且短路与代表条件性的AND THEN
如果COMMAND1 成功,将执行COMMAND2,否则,将不执行COMMAND2
COMMAND1 || COMMAND2 #或者短路或代表条件性的OR ELSE
如果COMMAND1 成功,将不执行COMMAND2,否则,将执行COMMAND2
! COMMAND #非,取反
# 结论如果 和 || 混合使用要在前||放在后 示例 [rootansible-salve1 ~]# id hehao /dev/null || useradd hehao # 前面执行不成功则执行后面的语句
[rootansible-salve1 ~]# id hehao /dev/null echo 此账户已存在
此账户已存在
[rootansible-salve1 ~]#
[rootansible-salve1 ~]# IP10.0.0.11;ping -c1 -w1 $IP /dev/null echo $IP is up || echo $IP is down
10.0.0.11 is down
[rootansible-salve1 ~]# IP192.168.80.1;ping -c1 -w1 $IP /dev/null echo $IP is up || echo $IP is down
192.168.80.1 is up
[rootansible-salve1 ~]# 示例磁盘空间的判断 # 查看磁盘空间占用率
[rootansible-salve1 shell]# df | grep ^/dev/nv | grep -oE [0-9]% | tr -d %
17
[rootansible-salve1 shell]# cat fd.sh
#!/bin/bash
WARNING10
SPACE_USEDdf | grep ^/dev/nv | grep -oE [0-9]% | tr -d %
[$SPACE_USED -gt $WARNING] echo 磁盘空间不足请尽快处理 | mail -s DISK Warning 1446528135qq.com
4.7 使用read命令命令来接受输入
read 是 Shell 内置命令用来从标准输入中读取数据并赋值给变量。如果没有进行重定向默认就是从键盘读取用户输入的数据如果进行了重定向那么可以从文件中读取数据
4.7.1 语法结构
read [option] [variables]
--options表示选项
--variables表示用来存储数据的变量可以有一个也可以有多个。
-- options和variables都是可选的如果没有提供变量名那么读取的数据将存放到环境变量 REPLY 中。
4.7.2 选项
Option说明-a array把读取的数据赋值给数组array从下标0开始-d delimiter把字符串delimiter指定读取结束的位置而不是一个换行符读取的数据不包括delimiter-e在获取用户输入的时候对功能键进行编码转换不会直接显示功能键对应的字符-n num读取num个字符而不是整行字符-p prompt显示提示信息提示内容为prompt-r原样读取(Raw mode),不会把反斜杠字符解释为转义字符-s静默模式(Silent mode),不会再屏幕上显示输入的字符。例如输入密码-t seconds设置超时时间单位为秒。如果用户没能按时完成返回一个非0的退出状态-u fd使用文件描述符fd作为输入源而不是标准输入类似于重定向 示例使用read给多个变量赋值并输出 [rootansible-salve1 shell]# vim info.sh
#!/bin/bash
read -p Enter some information name url age
echo 网站名字$name
echo 网址$url
echo 年龄$age
[rootansible-salve1 shell]# chmod x info.sh
[rootansible-salve1 shell]# ./info.sh
Enter some information hehao www.baidu.com 18
网站名字hehao
网址www.baidu.com
年龄18
[rootansible-salve1 shell]#
# 注意必须在一行内输入所有的值不能换行否则只能给第一个变量赋值后续变量都会赋值失败 示例只读取一个字符 # -n 1表示只读取一个字符运行脚本后只要用户输入一个字符立即就读取结束不等待用户按下回车键
[rootansible-salve1 shell]# vim info1.sh
#!/bin/bash
read -n 1 -p Enter a char char printf \n
echo ---------------------------------------------------------
echo $char
[rootansible-salve1 shell]# chmod x info1.sh
[rootansible-salve1 shell]# ./info1.sh
Enter a char a
---------------------------------------------------------
a 示例在指定时间内输入密码 #使用组合了多个命令这些命令会依次执行并且从整体上作为 if 语句的判断条件只要其中一个命令执行失败退出状态为非 0 值整个判断条件就失败了后续的命令也就没有必要执行
[rootansible-salve1 shell]# vim info2.sh
#!/bin/bash
ifread -t 20 -sp Enter password in 20 seconds(once) pass1 printf \n #第一次输入密码read -t 20 -sp Enter password in 20 seconds(again) pass2 printf \n #第二次输入密码[ $pass1 $pass2 ] #判断两次输入的密码是否相等
thenecho Valid password
elseecho Invalid password
fi
[rootansible-salve1 shell]# chmod x info2.sh
[rootansible-salve1 shell]# ./info2.sh
Enter password in 20 seconds(once)
Enter password in 20 seconds(again)
Valid password
[rootansible-salve1 shell]# 示例利用正则表达式 [rootansible-salve1 shell]# vim info3.sh
[rootansible-salve1 shell]# cat info3.sh
#!/bin/bash
read -p Are you rich? yes or no: ANSWER
[[ $ANSWER ~ ^[Yy]|[Yy][Ee][Ss]$ ]] echo You Are Rich || echo Good Good Study,Day Day up
[rootansible-salve1 shell]# chmod x info3.sh
[rootansible-salve1 shell]# ./info3.sh
Are you rich? yes or no: y
You Are Rich
[rootansible-salve1 shell]# ./info3.sh
Are you rich? yes or no: YeS
You Are Rich
[rootansible-salve1 shell]# 示例工作选项 [rootansible-salve1 shell]# vim backup.sh
#!/bin/bash
SRC/etc/
DEST/data/backup_date %F_%H-%M-%S
cp -a $SRC $DEST
[ $? -eq 0 ] echo 备份成功 || echo 备份失败
[rootansible-salve1 shell]# chmod x backup.sh
[rootansible-salve1 shell]# vim info4.sh
#!/bin/bash
cat EOF
请选择
1.备份文件
2.清理日志文件
3.软件升级
4.软件回滚
5.删库跑路
EOF
read -p 请输入上面的数字1-5 MENU
[ $MENU -eq 1 ] ./backup.sh
[ $MENU -eq 2 ] echo 清理日志文件
[ $MENU -eq 3 ] echo 软件升级
[ $MENU -eq 4 ] echo 软件回滚
[ $MENU -eq 5 ] echo 删除跑路
[rootansible-salve1 shell]# chmod x info4.sh
[rootansible-salve1 shell]# ./info4.sh
请选择
1.备份数据库
2.清理日志文件
3.软件升级
4.软件回滚
5.删库跑路
请输入上面的数字1-51
备份成功
[rootansible-salve1 shell]#