一、解释器
查看Linux系统支持的解释器:
[root@node1 shell]#cat /etc/shells
/bin/sh
/bin/bash
/sbin/nologin
/bin/dash
/bin/tcsh
/bin/csh
查看SHELL 环境变量:
[root@node1 shell]# echo $SHELL
/bin/bash
二、shell脚本执行方式
以下所有操作都在/export/shell目录下进行,请提前创建该目录:
mkdir -p /export/shell
1.sh执行脚本
sh执行,进入脚本的工作目录,然后使用对应的sh或bash来执行脚本,这种执行方式,脚本文件不需要具有可执行权限。
[root@node1 ~]# cd /export/data/shell/
[root@node1 shell]#sh hello.sh
hello world
2.工作目录执行
执行脚本时,先进入到脚本所在的目录,然后使用./脚本方式执行,这种执行方式,必须保证脚本文件具有可执行权限。
[root@node1 ~]#cd /export/data/shell/
[root@node1 shell]# chmod +x hello.sh
[root@node1 shell]# ./hello.sh
hello world
3.绝对路径执行
绝对路径中执行,指的是直接从根目录/到脚本目录的绝对路径,这种执行方式,必须保证脚本文件具有可执行权限。
[root@node1 ~]# /export/shell/hello.sh
hello world
三、变量
变量的定义需遵循的规则
变量名可以由字母、数字和下画线组成,但是不能以数字开头。
在Bash中,变量的默认类型都是字符串型,如果要进行数值运算,则必须使用特殊命令。
变量用等号"="连接值,"="左右两侧不能有空格。
变量值中如果有空格,则需要使用单引号或双引号包含,如test="hello world!"。双引号括起 来的内容"$"和反引号者都拥有特殊含义,而单引号括起来的内容都是普通字符。
在变量值中,可以使用转义符"\"。
不能使用bash里的关键字(可用help命令查看保留关键字)。
3.1定义变量
单引号里的内容原封不动的输出,双引号里有变量的调用则会调用变量
[root@node1 shell]# username="itcast"
[root@node1 shell]# echo $username
itcast
[root@node1 ~]# echo $usernamedb.log #这种方式不可以
.log
[root@node1 ~]# echo "$username"db.log #可以
itcastdb.log
[root@node1 ~]# echo ${username}db.log #可以
itcastdb.log
#脚本内容:test1.sh
#!/bin/bash
string="I am shell"
num=5
echo "a=${num},string=${string}"
[root@node1 shell]# sh test1.sh
a=5,string=I am shell
3.2 变量的其他赋值方式
可以使用read关键字从键盘获取内容赋值给变量
可以通过$(linux命令)或者$`linux命令`来执行linux命令,并将命令的执行结果赋值给变量
脚本内容:test2.sh
#!/bin/bash
echo "who are you?"
read name #从键盘获取变量的值
pwd_string=$(pwd) #将当前的绝对路径赋值给pwd_string变量
date_string=`date` #将当前时间赋值给date_string变量,注意这里使用的是反引号
echo "hello, $name"
echo $pwd_string
echo $date_string
执行脚本
[root@node1 shell]# sh test2.sh
who are you?
itcast
hello, itcast
/export/data/shell
2020年 05月 10日 星期日 16:50:21 CST
3.3只读变量
使用readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变
#!/bin/bash
myUrl="http://www.google.com"
readonly myUrl
myUrl="http://www.runoob.com"
#运行结果:
/bin/sh: NAME: This variable is read only.
3.4 删除变量
使用unset 命令可以删除变量,变量被删除后不能再次使用。unset 命令不能删除只读变量
#!/bin/sh
myUrl="http://www.runoob.com"
unset myUrl
echo $myUrl
#以上实例执行将没有任何输出
3.5环境变量
环境变量可以在/etc/profile中设置,环境变量的名字习惯上使用大写字母
可以使用env命令查看所有的系统环境变量
3.6特殊变量
变量 | 解释 |
$# | 命令行参数的个数 |
$n | $1表示第一个参数,$2表示第二个参数,以此类推 |
$0 | 当前程序的名称 |
$? | 前一个命令或许或函数的返回码 |
$* | 以“参数1 参数2 。。。”形式保存所有参数 |
$@ | 以“参数1”“参数2”。。。形式保存所有参数 |
$$ | 本程序的(进程ID号)PID |
$! | 上一个命令的PID |
3.7获取字符串长度
#!/bin/bash
string="jobs"
echo ${string} # 输出结果: jobs
echo ${#string} # 输出结果: 4
3.8提取子字符串
#!/bin/bash
string="敢于亮剑决不后退"
echo ${string:2:2} # 输出结果为: 亮剑
3.9算术运算符
下表列出了常用的算术运算符,假定变量a为10,变量b为20:
运算符 | 说明 | 举例 |
+ | 加法 | `expr $a + $b` 结果为30。 |
- | 减法 | `expr $a - $b` 结果为-10。 |
* | 乘法 | `expr $a \* $b` 结果为200。 |
/ | 除法 | `expr $b / $a` 结果为2。 |
% | 取余 | `expr $b % $a` 结果为0。 |
= | 赋值 | a=$b 将把变量 b 的值赋给 a。 |
== | 相等。用于比较两个数字,相同则返回true。 | [ a == b ] 返回 false。 |
!= | 不相等。用于比较两个数字,不相同则返回true。 | [ a != b ] 返回 true。 |
注意:条件表达式要放在方括号之间,并且要有空格,例如: [a==b] 是错误的,必须写成 [ a == b ]。
3.10流程控制
3.10.1语句判断
数字
运算符 | 说明 |
-eq | 检测两个数是否相等,相等返回true。 |
-ne | 检测两个数是否不相等,不相等返回true。 |
-gt | 检测左边的数是否大于右边的,如果是,则返回true。 |
-lt | 检测左边的数是否小于右边的,如果是,则返回true。 |
-ge | 检测左边的数是否大于等于右边的,如果是,则返回true。 |
-le | 检测左边的数是否小于等于右边的,如果是,则返回true。 |
字符串
判断符 | 说明 |
-n STRING | 字符串长度不为零 |
-z STRING | 字符串长度为0 |
= | 判断两个字符串是否一样 |
!= | 判断两个字符串是否不一样 |
文件
判断符 | 说明 |
-f | 存在且是普通文件 |
-d | 存在且是目录 |
-h | 存在且是符号链接 |
-e | 文件存在 |
–r | 文件存在并且可读 |
–w | 文件存在并且可写 |
–x | 文件存在并且可执行 |
3.10.2if语句
判断当前系统是否有多个ssh进程,如果有则打印true
#!/bin/bash
if [ $(ps -ef | grep -c "ssh") -gt 1 ]
then
echo "true"
fi
判断/media/cdrom文件是否存在,若不存在就去创建这个目录
#!/bin/bash
DIR="/media/cdrom"
if [ ! -e $DIR ]
then
mkdir -p $DIR
fi
根据年龄判断是否成年
#!/bin/bash
read -p "Enter your age(1-100):" age
if [ $age -ge 18 ]
then
echo '已经成年!'
else
echo '未成年!'
fi
4.以下实例判断两个变量是否相等
#!/bin/bash
echo "请输入a的值:"
read a
echo "请输入b的值:"
read b
if [ $a - $b ]
then
echo "a 等于 b"
elif [ $a -eq gt $b ]
then
echo "a 大于 b"
elif [ $a -lt $b ]
then
echo "a 小于 b"
else
echo "没有符合的条件"
fi
3.10.3for循环
1.顺序输出当前列表中的数字
#!/bin/bash
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
2.打印/root目录下所有文件的名字
#!/bin/bash
for file in $(ls /root)
do
echo $file
done
3.求1-100的和
#!/bin/bash
s=0
#从1加到100
for(( i=1;i<=100;i=i+1))
#定义循环100次
do
#每次循环给变量s赋值
s=$(($s+$i))
done
#输出从1加到100的和
echo "The sum of 1+2+..+100 is : $s"
3.10.4while循环
求1-100的和
#!/bin/bash
i=1
sum=0
while [ $i -le 100 ]
do
let sum+=i
let i++
done
echo $sum
3.10.5无限循环
#第一种
while :
do
command
done
#第二种
while true
do
command
done
#第三种
for (( ; ; ))
3.10.5case语句
模板
#!/bin/bash
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '你选择了 1'
;;
2) echo '你选择了 2'
;;
3) echo '你选择了 3'
;;
4) echo '你选择了 4'
;;
*) echo '你没有输入 1 到 4 之间的数字'
;;
esac
3.10.6跳出循环
break命令允许跳出所有循环(终止执行后面的所有循环)
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字:"
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的! 游戏结束"
break
;;
esac
done
continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环
#!/bin/bash
while :
do
echo -n "输入 1 到 5 之间的数字: "
read aNum
case $aNum in
1|2|3|4|5) echo "你输入的数字为 $aNum!"
;;
*) echo "你输入的数字不是 1 到 5 之间的!"
continue
echo "游戏结束"
;;
esac
done
3.10.7函数
#!/bin/bash
funWithReturn(){
s=0
#求1-n的和,$1为传入的第一个参数
for(( i=1;i<=$1;i=i+1))
do
s=$(($s+$i))
done
#返回计算结果
echo $s
return 0;
}
#调用函数,并传入参数,求1-100的和
#result用户获取函数的返回结果,也就是echo后边的内容
result=$(funWithReturn 100)
echo "1-$1的和:$result"
#状态码为0表示正常退出,非0表示不正常退出
echo "退出状态码: $? !
函数参数
#!/bin/bash
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第十个参数为 $10 !"
echo "第十个参数为 ${10} !"
echo "第十一个参数为 ${11} !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
3.10.8数组
Shell 数组用括号来表示,元素用"空格"符号分割开,语法格式如下:
#!/bin/bash
my_array=("A" "B" "C" "D")
echo "第一个元素为: ${my_array[0]}"
echo "第二个元素为: ${my_array[1]}"
echo "第三个元素为: ${my_array[2]}"
echo "第四个元素为: ${my_array[3]}"
使用@ 或 * 可以获取数组中的所有元素,例如:
#!/bin/bash
my_array[0]="A"
my_array[1]="B"
my_array[2]="C"
my_array[3]="D"
echo "数组的元素为: ${my_array[*]}"
echo "数组的元素为: ${my_array[@]}"
获取数组长度的方法与获取字符串长度的方法相同,例如:
#!/bin/bash
my_array[0]="A"
my_array[1]="B"
my_array[2]="C"
my_array[3]="D"
echo "数组元素个数为: ${#my_array[*]}"
echo "数组元素个数为: ${#my_array[@]}"
3.10.9遍历数组
#!/bin/bash
#第一种
my_arr=(AA BB CC)
for var in ${my_arr[*]}
do
echo $var
done
#第二种
my_arr=(AA BB CC)
my_arr_num=${#my_arr[*]}
for((i=0;i<my_arr_num;i++));
do
echo "-----------------------------"
echo ${my_arr[$i]}
done
3.10.10select
模板
#!/bin/bash
echo "What is your favourite OS?"
PS3="Please enter your choice:"
select var in "Linux" "Gnu Hurd" "Free BSD" "Other"
do
break;
done
echo "You have selected $var"
这里PS3作为select语句的shell界面提示符,注意:PS3一定要定义在select语句的前面
#!/bin/bash
echo "你想学习什么语言?"
PS3="请输入你的选择:" # 设置提示字符串
select var in java c++ shell python
do
case $var in
"java")
echo "恭喜你选择成功.java最牛"
;;
"c++")
echo "驱动开发 网络优化 go 语言"
;;
"shell")
echo "运维必会"
;;
python)
echo "人工智能"
esac
break # 如果这里没有break 将会进行无限循环
done
echo "你选择的是:$var"
3.11加载其它文件的变量
. filename # 注意点号(.)和文件名中间有一空格
或
source filename