shell编程之变量
变量:
- 字母、数字、下划线,不能超过255
- 数据类型:存储的都是字符串
- 变量分类:
- 用户自定义变量
- 定义:x=5,name=“jie cao”,等号两边不能有空格,有空格会认为是命令
- 调用:echo $变量名,
- 变量的叠加: x=123,
echo "$x"456
,echo ${x}456
- 不会做数值运算,默认字符串
- 变量查看:set [-u],u调用未声明变量会报错
- 变量删除:unset 变量名,没有
$
- 环境变量
- 环境变量是全局变量,自定义变量是局部变量
- 定义:export 变量名=变量值,或,变量名=变量值,export 变量名
- 查看:set,env
- $PATH,系统环境变量,把要执行的文件放到该文件下就能快速执行不需要绝对路径
$PATH="$PATH":/root/sh
,增加PATH变量的值
- PS1变量:命令提示符设置,echo $PS1
- \d显示日期,\t显示24小时制时间
- [\u@\h \W]$ -> [root@local shellstudy]
- $PATH,系统环境变量,把要执行的文件放到该文件下就能快速执行不需要绝对路径
- 删除:unset 变量名
- 当前语系变量
- 查看:locale,LANG=en_US.UTF-8 默认主语系
- 语系变量LANG
- echo $LANG
- locale -a | more,查看支持的语系
- vim /etc/sysconfig/i18n,下次开机启动时启动语系
- LANG=zh_CN.UTF-8,纯字符界面不支持中文,设置只是让Xshell支持中文显示
- 位置参数变量(在预定义变量中)
- $n,n是1-9,参数1,参数2…参数9
num1=$1 num2=$2 sum=$(($num1 + $num2))
,运行2.sh 10 20
- $*,返回所有参数,一个整体
- $@,返回所有参数,单独的
- $#,返回参数个数
- $n,n是1-9,参数1,参数2…参数9
- 预定义变量
- $?,返回上次执行命令结果,正确为0,不正确非0,逻辑与中就是根据这个处理的
- $$,当前运行进程的PID
- $!,返回后台进程的PID
- 接受键盘输入:
read [选项] [变量名]
- p 提示信息,t 描述,n 字符数,s 隐藏输入的数据
- read -p “Please input your name:” -t 30 -n 20 name,echo $name
- 用户自定义变量
shell编程之运算符
shell变量缺点:弱类型,默认字符串型
声明变量类型:declare [+|-] [选项] 变量名
-
- 设定类型,+ 取消类型,a 数组型,i 整数型,x 环境变量,r 制度变量,p 显示指定变量的被声明的类型
aa=11, bb=22, cc=$aa+$bb, echo $cc, declare -i cc=$aa+$bb, echo $cc
arr[0]=123, arr[1]=234, declare -a arr[2]=567, echo ${arr}, echo ${arr[2]}, echo ${arr[*]}
declare -x test=123
,相当于export test
- 设定类型,+ 取消类型,a 数组型,i 整数型,x 环境变量,r 制度变量,p 显示指定变量的被声明的类型
数值运算的方法:
- expr或let数值运算工具
aa=11, bb=22, dd=$(expr $aa + $bb)
,+ 左右两边必须有空格$(($aa+$bb))
与$[$aa+$bb]
变量测试:
x=${y-新值}
,unset y, x=$(y-2), echo $x
x=${y:-新值}
x=${y+新值}
x=${y:+新值}
x=${y=新值}
x=${y:=新值}
x=${y?新值}
x=${y:?新值}
shell编程之环境变量配置文件
环境变量配置文件:
- source 配置文件,或, . 配置文件
- 作用:配置文件会立即生效,不需要注销用户登录
- 登录相关配置文件:
/etc/profile,/etc/profile.d/*.sh,~/.bash_profile,~/.bashrc,/etc/bashrc
- 注销时配置文件:~/.bash_logout
- shell登录信息:/etc/issue
- 远程终端欢迎信息:/etc/issue.net,/etc/ssh/sshd_config
shell编程之正则表达式
通配符:* 任意内容,. 任意一个内容,[] 括号中的一个字符
正则表达式用来匹配文件中字符串的,是包含匹配,grep、awk、sed等支持正则表达式;通配符用来匹配文件名,ls、find、cp不支持正则表达式,使用通配符时是完全匹配。
grep "a\{3\}" reg.txt
,匹配大于等于三次的grep "a\{1,3\}" reg.txt
,1次以上grep "a\{3\}d" reg.txt
,添加定界符grep [0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\} reg.txt
字符截取:
- 行提取:
grep "/bin/bash" /etc/passwd | grep -v "root"
,查看除了root以外的用户 - 列提取:
cut [-fd] 文件名
,f 第几列,d 分隔符grep "/bin/bash" /etc/passwd | grep -v "root" | cut -f 1 -d ":"
cut -f 2 reg.txt
- 格式化输出:
printf "输出类型输出格式" 要输出的内容
- 输出类型:%ns 字符串,%ni 整数,%m.nf 浮点数,其中n 代表格式
- 输出格式:\a \b \f \n \r \t \v
printf "%s\t%s\t%s\n" 1 2 3 4 5 6
printf "%s\n" $(cat reg.txt)
- awk:
awk "条件1{动作1} 条件2{动作2}..." 文件名
- 条件(Pattern):
- 一般使用关系表达式作为条件
- BEGIN:
cat /etc/passwd | grep "/bin/bash" | awk 'BEGIN{FS=":"}{print $1 "\t" $3}'
- BEGIN:
- x > 10,x >= 10,x <= 10
- 一般使用关系表达式作为条件
- 动作(Action):
- 格式化输出
- 流程控制语句
awk '{printf $2 "\t" $3 "\n"}' student.txt
df -h | awk '{print $1 "\t" $3}'
,cat reg.txt | awk '$1>10 {print $2}'
- 条件(Pattern):
- sed替换:
sed [选项] '[动作]' 文件名
- 选项:n 只把sed修改的输出,e 允许多条sed命令,i 会将结果修改文件
- 动作:a 追加,c 行替换,i 插入,p 打印,s 字符串替换,d 删除
sed -n '2p' student.txt
,打印第二行sed '2d' student.txt
,删除两行sed 's/90/99/g' student.txt
,把所有的90替换为99
字符处理:
- 排序:
sort [选项] 文件名
- 选项:f 忽略大小写,n 以数值型排序,r 单项排序,t 指定分隔符, k n[,m] 指定字段范围
sort -t ":" -n -k 3,3 /etc/passwd
- 统计:
wc [选项] 文件名
- 选项:l 统计行数,w 单词数,m 字符数
shell编程之条件判断与流程控制
条件判断:
- 按照文件类型进行判断:
- -b 文件:块设备文件
- -c 文件:字符设备文件
- -d 文件(重要): 是否为目录,
[ -d /root/abc ] && echo yes || echo no
- -e 文件(重要):是否存在,
test -e /root/1.log
,[ -e /root/1.log ]
- -f 文件(重要):普通文件
- -L 文件:符号链接文件
- -p 文件,管道文件
- -s 文件:是否为非空
- -S 文件:套接字文件
- 按照文件权限判断
- 选项:r、w、x、u(SUID)、g(SGID)、k(SBit)
[ -w /root/2.txt ] && echo yes || echo no
,不会区分哪个用户
- 两个文件之间比较:
文件1 -nt 文件2
,文件1修改时间是否比文件2的新文件1 -ot 文件2
,文件1修改时间是否比文件2的旧文件1 -ef 文件2
,文件1是否和文件2的INODE号一致,是否是硬链接
- 两个整数比较:
- 选项:eq、ne、gt、lt、ge、le
[99 -ge 20] && echo yes || echo no
- 字符串的判断:
- 选项:z(为空)、n(为非空)、字符串1==字符串2、字符串1!=字符串2
[ -z $y ] && echo yes || echo no
aa=11 \ bb=22 \ [ "$aa" == "$bb" ] && echo yes || echo no
- 多重条件:
- 选项:a与,o或,!非
[ "$aa" == "$bb" -a "$aa" -gt 2 ] && echo yes || echo no
流程控制:
(1)if 语句:
# 单分支if语句
# 可以省略分号,then单独写作一行
if [ 条件判断式,就是test命令盘但 ] ; then
程序
if
# 双分支if语句
if [ 条件判断式 ]
then
条件成立时,执行的程序
else
条件不成立执行的语句
fi
# 多分支if语句
if [ 条件判断1 ]
then
条件1成立执行程序
elif [ 条件判断2 ]
then
条件2成立执行程序
...省略更多条件...
else
当所有条件都不成立时执行
fi
#!/bin/bash
# 判断当前登录用户是不是root
user=$(env | grep "USER" | cut -d "=" -f 2)
if [ "$user" == "root" ]
then
echo "Current user is root."
fi
# 判断当前磁盘的使用情况
disk=$(df -h | grep sda3 | awk '{print $5}' | cut -d "%" -f 1)
echo $disk 15
if [ "$disk" -gt "10" ]
then
echo "Disk use 10%."
fi
# 判断是不是目录
read -t 30 -p "Please input a dir:" dir
if [ -d "$dir" ]
then
echo "This is dir."
else
echo "This is not dir."
fi
# 查看Apache服务是否开启
service=$(ps aux | grep httpd | grep -v grep)
if [ -n "$service" ]
then
echo "$(date) httpd is ok!" >> ./autostart-acc.log
else
/usr/sbin/httpd -k start &> /dev/null
echo "$(date) restart httpd !!" >> ./autostart-err.log
fi
# 判断文件类型
read -p "Please input a filename: " file
# 文件为空
if [ -z "$file" ]
then
echo "Error,please input a filename."
# 直接退出,不执行后面的程序,在外面可以用 echo $? 查看
exit 1
# 不是一个文件
elif [ ! -e "$file" ]
then
echo "Your input is not a file."
exit 2
# 普通文件
elif [ -f "$file" ]
then
echo "$file is a regulare file!"
# 目录
elif [ -d "$file" ]
then
echo "$file is a directory!"
else
echo "$file id an other file!"
fi
(2)case语句:
case $变量名 in
"值1")
如果变量的值等于值1,则执行程序1
;;
"值2")
如果变量的值等于值2,则执行程序2
;;
...省略其他分支...
*)
如果变量的值都不是以上的值,则执行此程序
;;
esac
#!/bin/bash
read -t 30 -p "Please input yes/no: " cho
case "$cho" in
"yes")
echo "yes"
;;
"no")
echo "no"
;;
*)
echo "what the fuck"
;;
esac
(3)for循环:
# 第一种写法
for 变量 in 值1 值2 值3...
do
程序
done
# 第二种写法
for ((初始值;循环控制条件;变量变化))
do
程序
done
#!/bin/bash
# 解压压缩文件
cd /root/StudyLinux/shellstudy/for_tar
ls *.tar.gz > ls.log
for j in $( cat ls.log )
do
tar -xvf $j & > /dev/null
done
rm -rf ls.log
# 1到100的和
s=0
for (( i=0;i<=100;i=i+1 ))
do
s=$(( $s + $i ))
done
echo $s
(4)while和until循环:
while [ 条件判断式 ]
do
程序
done
until [ 条件判断式 ]
do
程序
done