SHELL 编程
shell 编程
变量赋值
-
变量赋值的几种方式
- 变量=数值
- 引用其他命令结果进行赋值 ip=`ps -ef|grep "mysql"`
- 交互式变量赋值 read -t设置超时时间 -s不显示输入信息(密码) -p 设置提示信息 #这里-t建议放最前面,放后面可能不生效
- 脚本位置参数传参 $1 $2 $3
-
shell编程默认赋值都是字符串,所以单引号 双引号 或者直接字符串都一样
[root@127 download]# name=test [root@127 download]# name1="test1" [root@127 download]# name2='test2' [root@127 download]# echo $name1 test1 [root@127 download]# echo $name2 test2 [root@127 download]# echo $name test [root@127 download]# -
单引号变量,不识别特殊语法,双引号变量,可以识别特殊语法,反引号中的命令结果会被保留下来
[root@127 download]# name=test [root@127 download]# name1="test1" [root@127 download]# name2='test2' # 双引号可以识别$变量名的用法,单引号不行 [root@127 download]# echo "$name1" test1 [root@127 download]# echo "$name" test [root@127 download]# echo "$name2" test2 [root@127 download]# echo '$name2' $name2 [root@127 download]# echo '$name1' $name1 [root@127 download]# echo '$name' $name # 反引号 [root@127 download]# test=`ls -ll` [root@127 download]# echo $test total 82644 drwxr-xr-x 17 501 501 4096 Mar 11 15:52 Python-3.6.12 -rw-r--r-- 1 root root 84623360 Aug 15 2020 Python-3.6.12.tar -
位置变量
$*和$@的区别,当$*和$@ 不被" "包围时,没什么区别,都是将接受的每个参数看成一份整体数据,彼此用空格间隔而已. 如果被" "包围,$* 还是把所有接受的数据当成一份数据, 而$@ 会把每份数据单独视为一份数据,彼此间是独立的 比如bash text.bash alex 180 "$@" 接受的参数是alex和180 而$* 接受的参数是"alex 180" #! /bin/bash echo '特殊变量$0 $1 $2的实践' echo '结果 : '$0 $1 $2 echo "##############################" echo '特殊变量$#的实践' echo '结果 : '$# echo "##############################" echo '特殊变量$*和$@的实践' echo '结果 : '$* echo "##############################" echo '结果 : '$@ 把下面保存为1.sh,运行结果如下 [root@django_env2 ~]# bash 1.sh alex 180 特殊变量$0 $1 $2的实践 结果 : 1.sh alex 180 ############################## 特殊变量$#的实践 结果 : 2 ############################## 特殊变量$*和$@的实践 结果 : alex 180 ############################## 结果 : alex 180 把下面保存为2.sh #! /bin/bash echo '打印\"\$*\"' for var in "$*" do echo "$var" done echo "#############" echo '打印\"\$@\"' for var in "$@" do echo "$var" done 运行结果如下 [root@django_env2 ~]# bash 2.sh alex 180 打印\"\$*\" alex 180 ############# 打印\"\$@\" alex 180 -
变量子串 截取,基础${#args} ${args} 截取${args:start:length} 删除${args#word} ${args%word} 替换${args/找谁/替换}
用test=congratulation示例 ${变量} 返回变量值 ${#变量} 返回变量长度,字符长度 计算字符串长度其他方法还有wc -l 比如cat 1.txt |wc -L #打印最长行数的字符串长度 还有expr length "$test"和awk的echo "$test" |awk '{print length($0)}' ${变量:start} 返回变量offset数值后的长度 echo ${test:2}>>ngratulation ${变量:start:length}提取offset之后的length限制的字符 echo ${test:2:3}>>ngr 无论是从后向前还是从前向后,匹配的字符串支持* ? 等通配符 而且匹配位置不支持字符串中间,必须是以XXX为开始或者XXX为结束才能匹配到 ${变量#word} 从变量开头删除最短匹配的word子串 比如a=abc123abc ${a#ab} >>c123abc ${变量##word} 从变量开头删除最长匹配的word 比如a=abc123abc ${a##a*c} >> 因为##匹配的是最长abc123abc ${变量%word} 从变量结尾删除最短匹配的word子串 ${变量%%word} 从变量结尾删除最长匹配的word ${变量/pattern/string} 用string代替第一个匹配的pattern ${变量//pattern/string} 用string代替所有的的pattern [root@localhost ~]# a="man man boy boy man" [root@localhost ~]# echo ${a/man/girl} girl man boy boy man [root@localhost ~]# echo ${a//man/girl} girl girl boy boy girl示例,来一个批量修改文件名的操作
touch test{1..5}.jpg >>> test1.jpg test2.jpg test3.jpg test4.jpg test5.jpg 先批量创建5个jpg文件 for i in `ls *.jpg` do mv $i `echo ${i/test/best}` done变量扩展用法 对于变量的值进行判断和处理
如果parameter变量为空,返回word字符串 ${parameter:-word} 如果parameter变量为空,则word代替变量并返回其值 这里如果parameter为空,则ret和parameter都为word的值 ret=${parameter:=word} 如果parameter变量为空,word当做stderr说粗话,否则输出变量值 ${parameter:?word} 如果parameter变量为空,什么都不做,如果不为空则返回word ${parameter:+word}示例,比如把这个对变量判断添加到find命令中,提高容错率
find ${dir_path:=/opt/mysql/} -name "*.tar" -type f -mtime +7表示状态的变量
$? 上一条命令/脚本返回值 0正常 非0失败 用来判断执行是否成功 $$ 当前运行脚本的pid,把pid记录到文件中用来kill $! 上一个运行脚本的pid $_ 上一个脚本或命令的最后一个参数 和esc+.一样
环境变量设置
环境变量一般指用export内置命令导出的变量,用于定义shell的运行环境
- 用户个人配置文件 ~/.bash_profile, ~/.bashrc 远程登陆用户特有文件
- 全局配置文件/etc/profile /etc/bashrc,且系统建议最好创建在/etc/profile.d/而不是直接修改主文件,全局配置文件,影响所有登陆系统的用户
- set 和declare 输出所有变量,包括全局变量和局部变量
- env 只显示全局变量
- unset 变量名,删除变量或者函数
- export 显示和设置环境变量值
- readonly 设置变量只对当前shell生效.
readonly name=test
环境变量文件加载顺序
bash一些基础的内置命令
- echo
-n 不换行输出
-e 解析字符串中的下面特殊字符
\n 换行
\r 回车
\t tab
\b 应使用字符之前或之间, 字符尾部跟\b 是没有效果的最前面使用 删除后面紧跟的字符,之间使用删除前一个字符
echo -e " \b哇\b哈哈"
哈哈
-
eval
把参数传给他,然后当命令执行 eval "cd /opt; ls -ll"
-
exec
不创建子进程,执行后续命令,且执行完毕后自动exit,下面就是执行date命令后退出了root账号
[root@django_env2 ~]# exec date 2022年 04月 06日 星期三 07:29:25 CST ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── Session stopped - Pressto exit tab - Press R to restart session - Press S to save terminal output to file
进程列表和子shell环境
shell的进程列表理念,要用到小括号() cd ~;ls;
检测是否在子shell环境中,输出BASH_SUBSHELL变量,如果是0,表示在当前shell环境,否则就是子shell运行的命令
一个小括号开启的是一个子shell命令(cd ~;ls;echo $BASH_SUBSHELL)
子shell嵌套运行
利用子shell,可以实现多进程的处理,提高程序并发执行效率.
比如运行(ls;echo $BASH_SUBSHELL;(cd /var;ls;echo $BASH_SUBSHELL))
运行结果
download nodejs860 ossutil python362 python_virtualenvwrapper redis-6.0.16 rh stunnel
1
account adm cache crash data db empty games gopher kerberos lib local lock log mail nis opt preserve run spool tmp www yp
2 # 代表第二个子shell
for循环
语法 for 变量 in 序列1~100 示例: for number in {1..100}
do 放循环体语句 do echo number
done 结束for循环 done
if 判断
if后面要有空格,且[后面、]前面都要有空格,然后是分号,最后是then
里面有多个条件判断 -eq(equal) 相等 -ne(inequality) 不相等 -gt(greater than) 大于 -lt(less than) 小于 -ge(greater equal) 大于或等于 -le(less equal) 小于或等于
语法:
if [ $? == 0 ];then #==也可以用-eq代替
执行脚本
fi
shell示例
用shell写一个简单的脚本,用ping探测域名是否会响应
#!/bin/bash
url=$1
ping -c2 -i0.2 -W0.5 $url >/dev/null 2>&1 # -c是ping的次数 -W是timeout -i是间隔时间
if [ $? -eq 0 ];then
echo "$url 正常"
else
echo "$url 不正常"
fi