shell 是一个命令解释器,侦听用户指令、启动这些指令、将结果返回给用户(交互式的shell)
shell 也是一种简单的程序设计语言、利用它可以编写一些系统脚本。
查看本机shell 信息:
cat /etc/shells --查看本支持的shell
echo $SHELL --查看当前支持的shell
shell 在执行命令时,各种命令的优先级:
别名 -> 关键字 -> 函数 -> 内置命令 -> 脚本
别名:命令的另一种形式,有些情况下可以简化命令的输入,例如可以将很长的命令定义成短别名。
别名的设置:
alias 别名= ' '
如: alias del='rm -i'
alias ll='ls -l'
alias 显示存在的别名
删除别名:unalias del
bash 初始化:
/etc/profile -> ~/.bash_profile -> /etc/profile.d/*.sh
-> ~/.bashrc -> /etc/bashrc
bash 退出时也会执行一些脚本
~/.bash_logout
bash 命令历史
默认情况下,shell 执行的命令会保留下来,保存的地方有两个:内存和~/.bash_history
保存下来后,可以查看,也可以上翻去执行。
执行的命令先放在内存中,退出窗口时写到 ~/.bash_history
历史查看:
history
cat ~/.bash_history
历史命令操作:
!! 执行前一个命令
!n 执行第n号命令,如 !1023
!$ 表示的是上一次命令的最后一个参数
如: mkdir /abc
cd !$
与history 相关的设置 (/etc/profile)
vim /etc/profile
HISTSIZE=1000 --内存中保存的最大记录条目
HISTFILESIZE=1000 --历史文件中保留的最大记录条目
HISTFILE --指定命令历史文件
禁用命令历史:
1) HISTSIZE 设置为0
2) 把历史命令文件链接到/dev/null
如: ln -s /dev/null ~/.bash_history
shell 中执行命令:
1、无条件执行多条命令
; 隔开
如:mkdir /abc ; cd /abc ;cp /etc/yp.conf /abc
2、有条件执行多条命令
&& 前一个命令执行成功后,再执行后一个(前面不成功,后面就不执行了)
|| 前一个命令执行不成功时,才执行后一个(前面成功了,后面就不执行了)
如:[tom@s100 ~]$ mkdir /aaa && cd /aaa && cp /etc/yp.conf /aa
[tom@s100 ~]$ mkdir /aaa || mkdir ~/aaa
3、子shell中执行
( ) 把命令括起来
例:(cd /etc/X11;ls)
4、命令替换 ` ` 或 $()
命令替换是将一个命令作为另一个命令的一部分,执行时被替换的部分先执行,执行的给果作为
参数传给外层命令
如: mkdir `echo $USER`
mkdir `date`
mkdir $(date)
返回值
每执行一个命令都有它的返回值,返回值用来标识命令的执行成功与否
查看上一个命令执行的返回值:echo $?
0 表示执行成功
shell 中的变量
shell 中的变量没有严格的类型之分,但不同数据还是有不同的运算符。
变量定义:
变量名=值
注:
1、变量名由字母、数字、下划线组成,不能以数字开头
2、变量区分大小写
3、shell 变量一般以大写命名(习惯,但不是要求)
如:a=3
获取变量值的方法:
$变量名
或者
${变量名} 尽可能用下面这个
如:
a=tt
echo "how are you" > $a_old.txt
echo "how are you" > ${a}_old.txt
shell 的变量运算
1、字符运算
字符连接
shell 的字符连接,无须任何符号,只需拼接起来即可
如:a=3;b=5;c=abcdefg
echo $a$b$c
字符处理
获取长度 ${#变量名}
例:a="abcdefg"
echo ${#a}
模式匹配 =~
如 if [[ $a =~ "^a" ]]
判断变量a是否以a开头
取子串 ${变量名:(+/-)n:n}
+n 从左边第n个位置开始取(第一个字符是0)
-n 从右边第n个位置开始取
n 取多少个
s="abcdefg"
echo ${s:(-3):1} --从倒数第3个开始,取1个
字符删除 ${变量名#*截止字符}
#*x 从左边开始删,遇到第一个x为止
##*x 从左边开始删,遇到最后一个x为止
%x* 从右边开始删除,遇到第一个x为止
%%d* 从右边开始删除,遇到最后一个x为止
str=/dir1/dir2/dir3/dir4/file.txt
echo {str#*d} --从左边开始,删到第一个d为止
ir1/dir2/dir3/dir4/file.txt
echo {str##*d} --从左边开始,删到最后一个d为止
ir4/file.txt
echo ${str%d*}
/dir1/dir2/dir3/
echo ${str%%d*}
/
basename 取完整路径中的文件名
basename /etc/sysconfig/network
network
basename $str
file.txt
2、算术运算
$[ ]
$(( ))
如:echo $[3*5]
echo $((3*8))
但要注意 shell 算数的能力比较差,小数处理有很多问题
如在程序需要计算小数,可用 bc 和 awk
如:
echo "scale=2;5/2" | bc
awk 'BEGIN {print 5/2}'
算术运算符:
+ - * / ** %
3、比较运算
数值比较
-eq 等于
-ne 不等于
-gt 大于
-lt 小于
-ge 大于等于
-le 小于等于
字符比较
= 等于
!= 不等于
> 大于
< 小于
-z string 字符是否为空
-n string 字符是否不为空
更多的内容可见 man test
一、if的基本语法:
if [ command ];then
elif [ command ];then
else
fi
二、文件/文件夹(目录)判断
[ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真。
[ -c FILE ] 如果 FILE 存在且是一个字特殊文件则为真。
[ -d DIR ] 如果 FILE 存在且是一个目录则为真。
[ -e FILE ] 如果 FILE 存在则为真。
[ -f FILE ] 如果 FILE 存在且是一个普通文件则为真。
[ -g FILE ] 如果 FILE 存在且已经设置了SGID则为真。
[ -k FILE ] 如果 FILE 存在且已经设置了粘制位则为真。
[ -p FILE ] 如果 FILE 存在且是一个名字管道(F如果O)则为真。
[ -r FILE ] 如果 FILE 存在且是可读的则为真。
[ -s FILE ] 如果 FILE 存在且大小不为0则为真。
[ -t FD ] 如果文件描述符 FD 打开且指向一个终端则为真。
[ -u FILE ] 如果 FILE 存在且设置了SUID (set user ID)则为真。
[ -w FILE ] 如果 FILE存在且是可写的则为真。
[ -x FILE ] 如果 FILE 存在且是可执行的则为真。
[ -O FILE ] 如果 FILE 存在且属有效用户ID则为真。
[ -G FILE ] 如果 FILE 存在且属有效用户组则为真。
[ -L FILE ] 如果 FILE 存在且是一个符号连接则为真。
[ -N FILE ] 如果 FILE 存在 and has been mod如果ied since it was last read则为真。
[ -S FILE ] 如果 FILE 存在且是一个套接字则为真。
[ FILE1 -nt FILE2 ] 如果 FILE1 has been changed more recently than FILE2, or 如果 FILE1 exists and FILE2 does not则为真。
[ FILE1 -ot FILE2 ] 如果 FILE1 比 FILE2 要老, 或者 FILE2 存在且 FILE1 不存在则为真。
[ FILE1 -ef FILE2 ] 如果 FILE1 和 FILE2 指向相同的设备和节点号则为真。
三、字符串判断
[ -z STRING ] 如果STRING的长度为零则为真 ,即判断是否为空,空即是真;
[ -n STRING ] 如果STRING的长度非零则为真 ,即判断是否为非空,非空即是真;
[ STRING1 = STRING2 ] 如果两个字符串相同则为真 ;
[ STRING1 != STRING2 ] 如果字符串不相同则为真 ;
[ STRING1 ] 如果字符串不为空则为真,与-n类似
四、数值判断
INT1 -eq INT2 INT1和INT2两数相等为真 ,=
INT1 -ne INT2 INT1和INT2两数不等为真 ,<>
INT1 -gt INT2 INT1大于INT1为真 ,>
INT1 -ge INT2 INT1大于等于INT2为真,>=
INT1 -lt INT2 INT1小于INT2为真 ,<</div>
INT1 -le INT2 INT1小于等于INT2为真,<=
五、复杂逻辑判断
-a 与
-o 或
! 非
exp1: 如果a>b且a
if (( a > b )) && (( a < c ))
或者
if [[ $a > $b ]] && [[ $a < $c ]]
或者
if [ $a -gt $b -a $a -lt $c ]
exp2:如果a>b或a
if (( a > b )) || (( a < c ))
或者
if [[ $a > $b ]] || [[ $a < $c ]]
或者
if [ $a -gt $b -o $a -lt $c ]
"||"和"&&"在SHELL里可以用,也就是第一个写成if [ a>b && a
输入输出:
输出: echo
格式:echo [option] 字符串
option:
-n 不换行
-e 对一些控制符加以处理
如 插入tab
a 发警告音
输入: read
格式:read [option] [var]
option:
-p 设置提示字符
-s 输入时不显示,如同输入密码
-t n 设置等待时间,如果过了指定的秒数,就返回一个非零的状态
-n n 设置只接收多个字符,达到这个字符个数n后,就自动回车
如:read -p “请输入你的姓名:" name
read -sp “请输入密码:" passwd
read -n 1 "是否继续:" jx
cut
语法:cut [option] [文件名]
option:
-b 取字节
-c 取字符
-f 取字段
-d 指定字段分隔符
范围表示:
N 第N项
N- 从第N项开始,到最后
N-M N-M 项
-M 从1到M
例:只显示 /etc/passwd 中的用户名信息
cut -d: -f1 /etc/passwd
shell 程序一般设计流程:
1、创建一个文件,把完成功能的每一步操作写到脚本文件中
2、设置文件的可执行权限
3、执行文件
例:写一程序从键盘读入两个数,输出最大数
[root@s100 script]# cat if1.sh
#!/bin/bash
#if 使用示例,显示两个数的最大数
read -p "请输入第一个数:" n1
read -p "请输入第二个数:" n2
max=$n1
if [ $n2 -gt $max ]
then
max=$n2
fi
echo "最大数是: $max"
流程控制:
分支结构
格式一:
if [ condition ] --注意括号两边有空格,condition 是个条件表达式
then
commands
fi
作用:判断 ccondition 条件是否成立,如果成立,执行中间的命令 commands
不成立不执行。
如: if [ $a -gt $b ]
then
echo "a大于b"
fi
if 可以接 条件表达式 如 if [ $a -gt $b ],也可以直接接一个命令
如 if mkdir /abc ,这时,会把命令的执行结果作为判断,如果成功执行
就相当于条件成立,如果执行不成功,就相当于条件不成立
格式二:
if [ condition ]
then
commands1
else
commands2
fi
作用:判断 condition 条件是否成立,如果成立,执行commands1,如果不成立
执行 commands2
如:if [ $a -gt $b ]
then
echo "a>b"
else
echo "b>=a"
fi
分支嵌套
分支嵌套是分支中包含分支
普通的分支形式:
if [ condition ]
then
commands
fi
或者
if [ condition ]
then
commands1
else
commands2
fi
嵌套后就:
if [ condition ]
then
if [ condition ]
then
commands1
else
commands2
fi
fi
if [ condition ]
then
if [ condition ]
then
commands1
else
commands2
fi
else
commands3
fi
如:
if [ $a -ge 0 ]
then
if [ $a -gt 0 ]
then
b=$a
else
b=0
fi
else
b=$[$a*-1]
fi
if [ ]
then
commands1
else
commands2
fi
例:输入文件,判断是否存在,如果存在,判断当前用户对它的权限
if [ -f $file ]
then
if [ -r ...
if [ -w ....
if [ -x ...
else
echo "文件不存在!"
exit 1
fi
用分支嵌套实现:
某产品 199 元一件,买5件或以上9折,10件或以上 85 折,输入购买件数,计算付款。
if [ $n -ge 5 ]
then
else
fi
多条件表示:
逻辑与
if [ condition1 -a condition2 ]
if [ condition1 ] && [ condition2 ]
if [[ condition1 && condition2 ]]
逻辑或
if [ condition1 -o condition2 ]
if [ condition1 ] || [ condition2 ]
if [[ condition1 || condition2 ]]
逻辑非(取反)
!