shell编程
初始shell
程序 语言 编程 ---------------------------------- 语言 自然语言:汉语、英语 计算机语言:c语言、c 、(java php python go shell) 编译型语言 c c java 解释型语言 php python bash 编译语言:编译语言首先编译源代码生成机器语言,然后运行机器代码(二进制)。像C/C 都是编译语言。 解释语言:源代码不是直接翻译成机器语言,而是先翻译成中间代码,然后由解释器解释中间代码。比如Python/JavaScript/Shell都是解释性语言 c 编译执行代码需要编译成编译执行代码cpu能认识的二进制码 x86指令集 java 编译型执行编译-->字节码,cpu不能直接运行,只能直接运行Java虚拟机执行 shell 解释语言执行
shell 定义
Shell 它也是一种程序设计语言,具有变量、关键字、各种控制语句、语法结构和使用shell程序设计语 文字可以编写功能强大、代码短的程序。 shell就是外壳,就是系统的外壳,我们可以通过shell控制和操作操作系统等命令linux中的shell命令就包括ls、cd、pwd等等,总结一下shell它是通过接收用户输入的命令解释器shell命令启动、停止程序运行或控制计算机。
shell分类与切换
[root@linux-server ~]# cat /etc/shells /bin/sh /bin/bash /sbin/nologin /usr/bin/sh /usr/bin/bash /usr/sbin/nologin #默认shell: bash shell #centos默认使用中脚本shell 为/usr/bin/sh 查看目前正在使用的内容shell [root@linux-server ~]# echo $SHELL /bin/bash shell的修改 # vim /etc/passwd 编辑登录shell
使用场景
Shell 能做什么? 1. 自动化批量系统初始化程序 (update,软件安装、时区设置、安全策略...)---初始化脚本 2. 自动化批量软件部署程序 (LAMP,LNMP,Tomcat,LVS,Nginx)---脚本的自动安装 3. 应用管理程序 (KVM)---虚拟机的批量创建和管理。 4. 日志分析处理程序(PV, UV, 200, !200,grep/awk)----akw、sed、grep、正则表达式 5. 自动备份恢复程序(MySQL完全备份/增量 Crond)-----恢复脚本的数据备份 6. 自动化信息采集和监控程序(收集系统/应用状态信息,CPU,Mem,Disk,Net,TCP Status,Apache,MySQL)--监控脚本 7. 配合Zabbix信息采集(收集系统/应用状态信息,CPU,Mem,Disk,Net,Apache,MySQL) 8. 9*9乘法表、俄罗斯方块、三角形、圣诞树、五角星、小火车、坦克大战、排名 9. Shell可以做任何操作和维护的事情(一切都取决于业务需求) shell 和ansible---批量自动化工具-自动化操作--ansible
shell 特性回顾
- shell常见元素
文件描述符和输出重定向: 在 shell最常用的程序FD (file descriptor) 大约有三个, 分别是: 0: Standard Input (STDIN) 1: Standard Output (STDOUT) 2: Standard Error Output (STDERR) 在标准条件下, 这些FD分别与以下设备相关: stdin(0): keyboard
键盘输入并返回到前端 stdout(1): monitor 正确返回值 输出到前端 stderr(2): monitor 错误返回值 输出到前端 >a.tx 1>a.txt 2>a.txt &>a.txt 1>&2 2>&1 一般来说, "1>" 通常可以省略成 ">". 1>&2 正确返回值传递给2输出通道 &2表示2输出通道,之前如果有定义标准错误重定向到某log文件,那么标准输出也重定向到这个log文件,如果此处错写成 1>2, 就表示把1输出重定向到文件2中. 2>&1 错误返回值传递给1输出通道, 同样&1表示1输出通道. 例子. 当前目录下只有a.txt,没有b.txt [root@linux-server ~]# touch a.txt [root@linux-server ~]# ls a.txt b.txt 1>file.out 2>&1 [root@linux-server ~]# cat file.out ls: cannot access b.txt: No such file or directory a.txt 现在, 正确的输出和错误的输出都定向到了file.out这个文件中, 而不显示在前端
bash 初始化
用户登录时相关的bash配置文件 (登录脚本)属于全局配置文件:
/etc/profile
/etc/profile.d/*.sh
/etc/bashrc
个人配置文件,每个用户的配置文件
~/.bsah_profile
~/.bashrc
#profile类的文件: 设定环境变量,运行命令或脚本,用户在登录的时候会自动生效
#bashrc类的文件: 定义命令别名
用户登录时加载bash配置文件的过程:
登录式shell加载配置文件过程
~/.bash_profile --> ~/.bashrc --> /etc/bashrc ---> /etc/profile --> /etc/profile.d/*.sh
#这里的优先级是影响范围最小的优先级最高
下面的文件为系统的每个用户设置环境信息Shell设置文件:
/etc/profile(系统级)启动时执行
这是系统最主要的shell设置文件,也是用户登陆时系统最先检查的文件,有关重要的环境变量都定义在此,其中包括 PATH,USER,MAIL,HOSTNAME,HISTSIZE,INPUTRC等。而在文件的最后,它会检查并执行/etc/profile.d/*.sh的脚本。
~/.bash_login(用户级)登录时执行
如果~.bash_profile文件不存在,则系统会转而读取.bash_login这个文件内容。这是用户的登陆文件,在每次用户登陆系统时,bash都会读此内容,所以通常都会将登陆后必须执行的命令放在这个文件中。
~/.bash_logout 离开时执行如果想在注销shell前执行一些工作,都可以在此文件中设置。 例如:
# vi ~.bash_logout
clear
仅执行一个clear命令在你注销的时候
~/.bash_history(用户级) #这个文件会记录用户先前使用的历史命令。
- bash shell 特性
补全 tab键 #yum -y install bash-completion
历史--history
别名---alias
快捷键---ctrl+c+l
前后台作业---jobs fg bg &
重定向 > >> <
管道 ---|
#命令排序执行: ; && ||
&&:逻辑与,前面执行成功,后面才执行。前面命令执行失败,后面命令也不执行
||:逻辑或,前面执行失败,后面执行,前面命令执行成功,后面不执行。
;:从左往右按顺序执行,不管前面执行成功与否,后面都执行
通配符:[] {
} ? *
正则表达式 脚本
- 历史命令
查看历史命令
[root@linux-server ~]# history
调用历史命令
上下健
!关键字
!历史命令行号
!! 执行上一条命令
!$ 上一条命令的最后一个参数
esc . 上一条命令的最后一个参数
Ctrl+r 在历史命令中查找,输入关键字调出之前的命令
别名
查看别名
[root@linux-server ~]# alias
永久设置
# vim /root/.bashrc
# source /root/.bashrc #让文件生效
小小技巧:显示历史命令执行时间
1.设置变量:
[root@linux-server ~]# vim /etc/profile #在最后添加
HISTTIMEFORMAT="%Y-%m-%d %H:%M:%S"
[root@linux-server ~]# source /etc/profile #让设置的环境变量生效
2.再次执行history查看结果
- Bash 部分快捷键
Ctrl+a 切换到命令行开始(跟home一样,但是home在某些unix环境下无法使用)
Ctrl+u 清除剪切光标之前的内容
Ctrl+k 清除剪切光标之后的内容
ctrl+y 粘贴刚才所删除的字符
Ctrl+r 在历史命令中查找,输入关键字调出之前的命令
Ctrl+l 清屏
Ctrl+c 终止
Ctrl+e 切换到命令行末尾
- 通配符置换
#在 Shell命令中,通常会使用通配符表达式来匹配一些文件
*,?,[],{}
例:
字符 含义 实例
* 匹配 0 或多个字符 a*b a与b之间可以有任意长度的任意字符, 也可以一个也没有, 如aabcb, axyzb, a012b, ab。
? 匹配任意一个字符 a?b a与b之间必须也只能有一个字符, 可以是任意字符, 如aab, abb, acb, a0b 。
[list] 匹配 list 中的任意单一字符 a[xyz]b a与b之间必须也只能有一个字符, 但只能是 x 或 y 或 z, 如: axb, ayb, azb 。
[!list] 匹配 除list 中的任意单一字符 a[!0-9]b a与b之间必须也只能有一个字符, 但不能是阿拉伯数字, 如axb, aab, a-b。
[c1-c2] 匹配 c1-c2 中的任意单一字符 如:[0-9] [a-z] a[0-9]b 0与9之间必须也只能有一个字符 如a0b, a1b... a9b。
{string1,string2,...} 匹配 sring1 或 string2 (或更多)其一字符串 a{abc,xyz,123}b a与b之间只 能是abc或xyz或123这三个字符串之一。
[root@linux-server tmp]# rm -rf ./*
[root@linux-server tmp]# touch aabcb axyzb a012b ab acb
[root@linux-server tmp]# ls
a012b aabcb ab acb axyzb
[root@linux-server tmp]# ls a*b
a012b aabcb ab acb axyzb
[root@linux-server tmp]# ls a?b
acb
[root@linux-server tmp]# rm -rf ./*
[root@linux-server tmp]# touch axb ayb azb axyb
[root@linux-server tmp]# ls
axb axyb ayb azb
[root@linux-server tmp]# ls a[xy]b
axb ayb
[root@linux-server tmp]# ls a[!xy]b
azb
[root@linux-server tmp]# ls a[!x]b
ayb azb
[root@linux-server tmp]# rm -rf ./*
[root@linux-server tmp]# touch a0b a1b a9b
[root@linux-server tmp]# ls a[0-9]b
a0b a1b a9b
[root@linux-server tmp]# rm -rf ./*
[root@linux-server tmp]# touch aabcb axyzb a012b ab
[root@linux-server tmp]# ls a{abc}b
ls: cannot access a{
abc}b: No such file or directory
[root@linux-server tmp]# ls a{abc,xyz}b
aabcb axyzb
[root@linux-server tmp]# ls a{abc,xyz,012}b
a012b aabcb axyzb
shell 脚本规范
[root@linux-server ~]# vim helloworld.sh ---.sh代表这个文件是个shell脚本,
拓展名后缀,如果省略.sh则不易判断该文件是否为shell脚本
1. #!/usr/bin/env bash ---shebang蛇棒, 解释器, 翻译 2. #
2. #
3. # Author: soso666
4. # Email: soso666@163.com ---这就是注释, 你没看错
5. # Github: https:github.com/soso666
6. # Date: 2019/12/24
7. printf "hello world\n"
功能说明:打印hello world
[root@linux-server ~]# sh helloworld.sh
hello world
[root@linux-server ~]# chmod +x helloworld.sh
[root@linux-server ~]# ./helloworld.sh
[root@linux-server ~]# /root/helloworld.sh
hello world
第一行: “#!/usr/bin/env bash”叫做shebang, shell语法规定shell脚本文件第一行为整个文件的解释器
第二行: 为“#”开头的行为注释行默认不会被程序所读取, 用来说明文件及标定所属人员使用, 也可用来解释程序
第七行: 为格式化打印语句printf, printf可以把后面的“hello world”打印到指定的终端中, \n 为换行符
bash 脚本测试:
1.这将执行该脚本并显示所有变量的值
[root@linux-server ~]# sh -x /root/helloworld.sh
+ printf 'hello world\n'
hello world
2.不执行脚本只是检查语法模式,将返回所有错误语法
[root@linux-server ~]# sh -n /root/helloworld.sh
3.执行脚本前把脚本内容显示在屏幕上
[root@linux-server ~]# sh -v /root/helloworld.sh
#!/usr/bin/env bash
#
# Author: soso666
# Email: soso666@163.com
# Github: https:github.com/soso666
# Date: 2019/12/24
printf "hello world\n"
hello world
变量的类型
变量:bash作为程序设计语言和其它高级语言一样也提供使用和定义变量的功能,简单说就是让一个特定的字符串代表不固定的内容 a=123,echo $a #分为:预定义变量、环境变量、
自定义变量、位置变量
预定义变量:预定义的特殊变量有着特殊的含义,用户不可以更改,所有的预定义变量都由$符号和另外一个符号组成,常用的预定义特殊变量如下:
$$ 当前进程PID
$? 命令执行后的返回状态:0 为执行正确,非 0 为执行错误
$# 位置参数的数量
$* 所有位置参数的内容
$@ 显示所有的参数
$! 上一个后台进程的PID (wait命令中使用,后面讲)
[root@linux-server ~]# echo $? 最后一次执行的命令的返回状态。如果这个变量的值为 0,则证明上一条命令正确执行;如果这个变量的值为非 0 ,则 证明上一条命令执行错误
[root@linux-server ~]# echo $$ 当前进程的进程号(PID)
[root@linux-server ~]# echo $! 后台运行的最后一个进程的进程号(PID)
[root@linux-server ~]# ls
anaconda-ks.cfg a.txt b.txt file.out helloworld.sh #ls命令正确执行
[root@linux-server ~]# echo $?
0
#预定义变量"$?"的值是0,证明上一条命令正确执
[root@linux-server ~]# sleep 3000 &
[1] 1418
#符号"&"的意思是把命令放入后台执行
[root@linux-server ~]# echo $!
1418
自定义变量:就是自己设置的变量只能在当前终端和脚本中使用
变量名称=值 #定义变量
#变量名称:只能由字母,数字,下划线组成,不能以数字开头;
#注意:应该让变量名称有意义;
= 赋值符号 前后不能有空格 ;
值: 所有的字符串和数字都可以;
引用变量: $变量名 或 ${变量名}。
示例:
临时变量,仅当前终端可用
[root@linux-server ~]# a=100
[root@linux-server ~]# echo $a
100
[root@linux-server ~]# echo $aa # 这里输出为空,因为解释器认为$aa是变量
[root@linux-server ~]# echo ${a}a
100a
查看变量: echo $变量名
取消变量: unset 变量名,仅在当前shell中有效
环境变量:shell在开始执行时已经定义好的,就是系统执行环境的一些设置
# env #env是 environment (环境) 的简写,所有的环境变量(包含自定义的环境变量)
# set #列出系统中所有的变量,包括自定义的变量
export 变量名 #使自定义的变量成为环境变量,才使用这个参数。环境变量拥有可继承性:export之后就拥有继承性环境变量可以被向下继承,可用unset取消
临时生效
[root@linux-server ~]# IPADDR=192.168.1.1
[root@linux-server ~]# echo $IPADDR
192.168.1.1
永久生效
写到4个登陆脚本中 ~/.bashrc ~/profile 更好放在/etc/profile.d/目录下建立独立的环境变量配置文件
[root@linux-server ~]# vim /etc/profile.d/test.sh
IPADDT=192.168.1.1
[root@linux-server ~]# source /etc/profile.d/test.sh #让环境变量生效
[root@linux-server ~]# echo $IPADDT
192.168.1.1
常用环境变量:USER UID HOME HOSTNAME PWD PS1 PATH
PATH:存储所有命令所在的路径
#子进程 仅会继承父 shell 的环境变量, 不会继承父 shell 的自定义变量
[root@localhost ~]# bash # 打开一个子 shell
[root@localhost ~]# export a=hello # 在 子 shell 声明一个环境变量
[root@localhost ~]# bash # 在子 shell 中再打开一个 子 shell
[root@localhost ~]# echo $a # 变量可以生效
hello
[root@localhost ~]# exit # 退出 子 shell 的 子 shell
exit
[root@localhost ~]# exit # 退出 子 shell
exit
[root@localhost ~]# echo $a # 在 当前 shell 中, 其子 shell 声明的环境变量是无效的
[root@localhost ~]#
练习一
编写一个shell脚本,用于搜集其执行主机的信息,打印结果如下:
[root@linux-server ~]# mkdir /opt/test/script
[root@linux-server ~]# cd /opt/test/script
[root@linux-server script]# vim test.sh
[root@linux-server script]# chmod +x test.sh
[root@linux-server script]# ./test.sh
现在的时间是: 2020-08-22-17:34:03
当前的用户是: root
当前的用户标识: 0
当前的主机名称是: linux-server
当前可用网卡IP是: 192.168.246.148/24
##脚本源码如下
#!/usr/bin/bash
# 获取主机基本信息
time=`date +%F-%T`
ip=`ip a | grep ens33 | awk 'NR==2 {print $2}'`
echo "现在的时间是:" $time
echo "当前的用户是:" $USER
echo "当前的用户标识:" $UID
echo "当前的主机名称是:" $HOSTNAME
echo "当前可用网卡IP是:" $ip
取当前系统分区剩余空间:
[root@linux-server script]# df -Th | awk 'NR==6 {print $5}'
489M
取当前系统剩余内存:
[root@linux-server script]# echo "现在的剩余内存是:"`free -m |awk 'NR==2{print $4}'`
现在的剩余内存是:16G
取当前cpu平均负载:
[root@linux-server script]# echo 现在cpu的`uptime | cut -d, -f3-` #-d指定分隔符,-f指定显示区域,3-第三列以后(包括第三列)
现在cpu的 load average: 0.00, 0.01, 0.05
方式二:
[root@linux-server script]# echo 现在cpu的`uptime | awk -F "," '{print $3,$4,$5}'`
现在cpu的 load average: 0.00 0.01 0.05
练习二
编写一个脚本实现收集主机的基本信息,最后脚本还会将这些信息写入一个日志文件.
[root@linux-server script]# vim xinxi.sh
#!/bin/bash
#获取主机基本信息
centime=`date '+%Y-%m-%d %H:%M:%S'`
nowtime=`uptime |awk '{print $1}'`
username=$USER
verage=`uptime |awk -F',' '{print $3,$4,$5}'`
myname=xuange
cat >>file1.txt <<EOF echo "时间:$centime" echo "系统的当前时间是: $nowtime" echo "系统当前负载: $verage" echo "当前的用户是: $username" echo "我的名字是: $myname" EOF
[root@linux-server script]# chmod +x xinxi.sh
[root@linux-server script]# ./xinxi.sh
[root@linux-server script]# cat file1.txt
===========================================================
位置变量也叫位置参数:在脚本代码中调用通过命令行传递给脚本的参数
$1 $2 $3 $... #分别对应传递给脚本内容里面的第1、第2等参数
例子:
# /test.sh start #start是第1个位置参数
#/test.sh 2 3 5 hello #2是第1个位置参数,3是第2个位置参数...依次类推
例子:
[root@linux-server ~]# cd /opt/test/script/
[root@linux-server script]# vim weizhi.sh
#!/usr/bin/bash
echo 我的第一个位置参数是:$1
echo 我的第二个位置参数是:$2
echo 我的第三个位置参数是:$3
echo 我的第四个位置参数是:$4
echo 一共有 $# 个位置参数
echo 你输入的参数分别是:$*
[root@linux-server script]# chmod +x weizhi.sh
[root@linux-server script]# ./weizhi.sh 1 3 4 6
我的第一个位置参数是:1
我的第二个位置参数是:3
我的第三个位置参数是:4
我的第四个位置参数是:6
一共有 4 个位置参数
你输入的参数分别是:1 3 4 6
变量运算
算式运算符: +、-、*、/、()、%取余(取模)
如:(5+3)*2
运算方式:$(()) $[] expr
$(()):例子
# echo $(( 5+2-(3*2)/5 ))
6
# echo $(((3*2)/5))
1
$[]:例子
# echo $[ 5 + 2 - (3*2)/5 ]
6
expr:例子
# expr 5 + 3
8
#注意:运算符号两边的空格必须写
乘法运算:
[root@linux-server script]# expr 5 \* 3
15
[root@linux-server script]# expr 5 '*' 3
15
#脚本中常用的方式
echo "$a和$b的和是: `expr $a '+' $b`"
=================================================================
取1到6之间的随机数:
# echo $RANDOM
# echo $(($RANDOM % 6 + 1))
5
取1-10之间的随机数:
# echo $(($RANDOM % 10 + 1)
5
这串代码特别简单,就是利用RANDOM这个随机数生成器进行取余就能够实现,至于为什么取余时需要+1是因为在取余时如果被整除那么余数会是0,这样就不在限定范围内了
浮点运算
bash本身不能做小数计算:需要bc命令转换
# yum install -y bc
# echo "2.6*4" | bc
# echo "2^4" | bc
变量引用
#转义:\
1.当一个字符被引用时,其特殊含义被禁止,把有意义的变的没意义,把没意义的变的有意义
转义案例:
[root@linux-server script]# echo you now $1250
you now 250
[root@linux-server script]# echo you now \$1250
you now $1250
完全引用:'' #强引 硬引 #指的是被引号包围起来的变量名不会进行不会进行解析,原样变量名原样输出,这种方式比较适合定义显示纯字符串的情况,不希望解析变量、命令等的场景。
部分引用:"" #弱引 软引 #指的是被引号包围起来的变量名会先进行解析,然后将变量的解析结果输出来。这种方式适合字符串中附带有变量和命令并且想将其解析后再输出的变量定义。
例子:
[root@linux-server script]# num=1
[root@linux-server script]# echo 1901班有$num个女生
1901班有1个女生
[root@linux-server script]# echo "1901班有$num个女生"
1901班有1个女生
[root@linux-server script]# echo '1901班有$num个女生'
1901班有$num个女生
======================================================
#读取用户标准输入:read
read:功能就是读取键盘输入的值,并赋给变量
#read -t 5 var
#read -p "提示信息" var
read后面的变量var可以只有一个,也可以有多个,这时如果输入多个数据,则第一个数据给第一个变量,第二个数据给第二 个变量,如果输入数据个数过多,则最后所有的值都给最后一个变量
#!/usr/bin/bash
read -p "请输入你的用户名和密码还有你的年龄: " name pass age
echo "你的名字是 $name"
echo "你的密码是 $pass"
echo "你的年龄是 $age"
案例1:
[root@linux-server script]# vim readtest.sh
#!/bin/bash
# read test
read -p "请输入你的银行卡帐号" num
read -p "请在五秒内输入密码" -t 5 pass
echo "你的密码错误!"
[root@linux-server script]# ./readtest.sh
案例2: #-s 选项 能够使read命令中输入的数据不显示在监视器上
[root@linux-server script]# vim readtest3.sh
#!/bin/bash
read -s -p "Enter your password: " pass
echo "your password is $pass"
exit 1
[root@linux-server script]# chmod +x readtest3.sh
[root@linux-server script]# ./readtest3.sh
========================================================
取消屏幕回显
[root@linux-server script]# stty -echo #回车测试
[root@linux-server script]# stty echo #恢复回显
显示变量长度
[root@linux-server script]# a=123
[root@linux-server script]# echo ${#a} #表示$var的长度
3
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
练习:
[root@linux-server script]# cat d.sh
echo 1.配置yum客户端
echo 2.添加A记录
echo 3.一键安装lamp环境
echo 4.一键配置静态IP
read -p "请选择你想使用的功能(1/2/3/4):" num
con_ip(){
echo 这是配置IP地址的小工具
}
case $num in
1):
;;
2):;;
3):
;;
4)con_ip
;;
*)
echo "你输入的不正确!请按提示输入"
;;
esac
[root@linux-server script]# chmod +x d.sh
[root@linux-server script]# ./d.sh
脚本运行
创建bash脚本(shell脚本)
1.创建脚本文件
指定命令解释器
注释
编写bash指令集合
2.修改权限
bash脚本执行
# chmod +x script
# ./scripts
# /shelldoc/scripts
# source 和./scripts 使用当前shell执行 比如cd /tmp会改变当前shell环境,但是其他的方式不会
# bash scripts
变量置换
命令替换
取命令结果用。把命令的结果拿出来
[root@linux-server ~]# a=`date +%m%d`
[root@linux-server ~]# echo $a
1225
[root@linux-server ~]# a=$(date +%m-%d)
[root@linux-server ~]# echo $a
12-25
#反引号亦可用$() 代替
变量替换
一 ${parameter:-word}
若 parameter 为空或未设置,则用 word 代替 parameter 进行替换,parameter 的值不变,若 parameter 不为空,则不替换,parameter 的值不变
# unset b
# echo ${b:-3}
-3
# echo $b
#
二 ${parameter:=word}
若 parameter 为空或未设置,则用 word 代替 parameter 进行替换,parameter 的值改变,若 parameter设置了,则不替换,parameter的值不变
# unset b
# echo ${b:=3}
3
# echo $b
3
#
三 ${parameter:+word}
若 parameter 设置了值,则用 word 代替 parameter 进行替换,parameter 的值不变
# unset b
# echo ${b:+3}
#
# echo $b
#
举个例子:
#!/bin/bash
echo "======================="
echo " 目前的版本有: "
echo " mysql-8.0"
echo " mysql-5.7"
echo " 默认版本为: MySQL-8.0"
echo "======================="
read -p "请输入你要选择的版本" Num
Num=`echo ${
Num:=8.0}`
echo "您选择的版本为$Num,稍后给你安装......"
总结如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ApdaG8qi-1652375367998)(assets\shell变量替换.jpg)]
变量替换-匹配截取
索引及切片
[root@linux-server ~]# a=12345678
[root@linux-server ~]# echo ${a:5} #从左往右第5位开始截取,留下后三位
678
[root@linux-server ~]# echo ${a:3:4} #从第3位开始截取,留下后四位的,剩下的都不要。
4567
[root@linux-server ~]# echo ${a:2:-1} #从左往右第2位开始截取,从右往左截取第一位
34567
[root@linux-server ~]# echo ${a:2:-2}
3456
参数解释:
用冒号截取:echo $a: : :
从哪里截取留那里。
脚本案例:
[root@localhost ~]# vim test11.sh
#!/usr/bin/bash
read -s -p "请输入您的11位手机号 " phone
echo
echo "你的手机号是 $phone"
echo "手机号后四位是 ${phone:7}"
匹配截取
语法:
${变量#关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最短数据切除
${变量##关键词} 若变量内容从头开始的数据符合『关键词』,则将符合的最长数据切除
${变量%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最短数据切除
${变量%%关键词} 若变量内容从尾向前的数据符合『关键词』,则将符合的最长数据切除
参数解释:
*:表示全部字符。
%:最短尾匹配;
%%:最大尾匹配
%:从右往左
#:从左往右
实战
[root@linux-server ~]# url=www.sina.com.cn
[root@linux-server ~]# echo ${#url} #获取变量的长度
15
[root@linux-server ~]# echo ${url} #正常显示变量
www.sina.com.cn
匹配截取
[root@newrain ~]# echo ${url#*.} 从前往后匹配到“.”最短匹配
sina.com.cn
[root@newrain ~]# echo ${url##*.} 从前往后匹配到“.”,最长匹配
cn
[root@newrain ~]# echo ${url%.*} 从后往前匹配到“.”,最短匹配
www.sina.com
[root@newrain ~]# echo ${url%%.*} 从后往前匹配到“.”,最长匹配
www
[root@newrain ~]# echo ${url#a.} #不加*
www.sina.com.cn
[root@newrain ~]# echo ${url#*a.} #加*
com.cn
[root@localhost ~]# vim mail.sh
脚本案例:
#!/usr/bin/bash
read -p "请输入你的邮箱 " mail
echo "你的邮箱是$mail"
echo "你的邮箱服务器是${mail#*@}"
mail_host=${mail#*@}
case $mail_host in
163.com)
echo "网易服务器"
;;
126.com)
echo "126服务器"
;;
qq.com)
echo "qq邮箱"
;;
*)
echo "您输入的邮箱不正确"
exit 2
esac
变量内容的替换
语法
${变量/旧字符串/新字符串} 若变量内容符合『旧字符串』则『第一个旧字符串会被新字符串替代』
${变量//旧字符串/新字符串} 若变量内容符合『旧字符串』则『全部的旧字符串会被新字符串替代』
实战
[root@linux-server ~]# a=123456123789
[root@linux-server ~]# echo ${a/1/} #第一次匹配的被替换
23456123789
[root@linux-server ~]# echo ${a/1/0} #第一次匹配到1替换成0
023456123789
[root@linux-server ~]# echo ${a//1/} #全局的匹配被替换
2345623789
[root@linux-server ~]# echo ${a//1/x} #全局匹配到1替换成x
x23456x23789
例:
file=/dir1/dir2/dir3/my.file.txt
${file#*/}: 拿掉第一条 / 及其左边的字符串:dir1/dir2/dir3/my.file.txt
${file##*/}: 拿掉最后一条 / 及其左边的字符串:my.file.txt
${file#*.}: 拿掉第一个 . 及其左边的字符串:file.txt
${file##*.}: 拿掉最后一个 . 及其左边的字符串:txt
${file%/*}: 拿掉最后条 / 及其右边的字符串:/dir1/dir2/dir3
${file%%/*}: 拿掉第一条 / 及其右边的字符串:(空值)
${file%.*}: 拿掉最后一个 . 及其右边的字符串:/dir1/dir2/dir3/my.file
${file%%.*}: 拿掉第一个 . 及其右边的字符串:/dir1/dir2/dir3/my
记忆的方法为:
# 是去掉左边(在键盘上 # 在 $ 之左边)
% 是去掉右边(在键盘上 % 在 $ 之右边)
单一符号是最小匹配;两个符号是最大匹配(贪婪匹配)。
basename & dirname
basename 命令
basename 是去除目录后剩下的名字,取文件名
例:
[root@linux-server ~]# temp=/home/temp/1.test
[root@linux-server ~]# base=`basename $temp`
[root@linux-server ~]# echo $base
1.test
dirname 是获取目录名
例:
[root@linux-server ~]# temp=/home/temp/1.test
[root@linux-server ~]# dir=`dirname $temp`
[root@linux-server ~]# echo $dir
/home/temp
shell编程-流程控制
shell编程-条件结构
测试-----test 条件 #条件为真返回 0,条件为假返回 1 #语法------[ 条件 ] test 能够理解3中类型的表达式 1.文件测试 2.字符串比较 3.数字比较 字符串 -n STRING the length of STRING is nonzero -n 字符串的长度 不是零成功。 -z STRING the length of STRING is zero -z 字符串长度。是零成功 #对于未定义或赋予空值的变量将是为空串。 STRING1 = STRING2 (等于) the strings are equal STRING1 != STRING2 (不等于) the strings are not equal # vim string.sh #!/usr/bin/bash while : #:默认值为真 do read -p "请输入你的密码: " a pass=123456 if [ -z $a ];then echo "您输入的密码不能为空" exit 1 else if [ 标签:
电容柜akw