1、概述
编写脚本尽量在Linux 系统上进行,否则存在编码的转换的问题,导致在Linux上无法执行
Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁。Shell 既是一种命令语言,又是一种程序设计语言;
最简单的shell 脚本如下:
#! /bin/bash #告诉系统需要用什么解释器来执行脚本
echo "hello,world!"
2、变量
变量定义,需要满足以下要求:
- 只包含字母、数字和下划线;
- 不能以数字开头;
- 避免使用shell关键字;
- 避免使用特殊符号或空格;
2.1 变量类型
Shell 支持不同类型的变量,其中一些主要的类型包括:
2.1.1 字符变量
在 Shell中,变量通常被视为字符串,你可以使用单引号'或双引号 " 来定义字符串;
2.1.2 整型变量
在一些Shell中,你可以使用 declare 或 typeset 命令来声明整数变量。
declare -i my_integer=42 #如果尝试将非整数值赋给它,Shell会尝试将其转换为整数
2.1.3 数组变量
Shell 也支持数组,允许你在一个变量中存储多个值。bash 只支持一维数组(不支持多位数组),没有限制数组大小,与C语言相似,数组的元素下标由0开始编号;
数组定义
在Shell 中,用括号()表示数组,数组元素用空格符号分隔开,数组定义形式如下:
数组名=(值1 值2 ...值n)
例如:
array_name=(value0 value1 value2 value3)
#or
array_name=(
value0
value1
value2
value3
)
#还可以单独定义数组的各个分量
array_name[0]=value0
array_name[1]=value1
array_name[n]=valuen
读取数组
读取数组元素值的一般格式是:
${数组名[下标]} #起始0
# 例如
valuen=${array_name[n]}
使用 @ 符号可以获取数组中的所有元素,例如:
echo ${array_name[@]}
获取数组长度
# 取得数组元素的个数
length=${#array_name[@]}
# 或者
length=${#array_name[*]}
# 取得数组单个元素的长度
length=${#array_name[n]}
关联数组
Bash 支持关联数组,可以使用任意字符串,或者整数的下标来访问数组元素:关联数组使用 declare 命令来声明,语法格式如下:
declare -A array_name # -A 选项就是用于声明一个关联数组。关联数组的键是唯一的
#example
declare -A site=(["google"]="www.google.com" ["runoob"]="www.runoob.com" ["taobao"]="www.taobao.com")
#or
declare -A site
site["google"]="www.google.com"
site["runoob"]="www.runoob.com"
site["taobao"]="www.taobao.com"
2.1.4 字符串变量
字符串可以用单引号,也可以用双引号,不过使用单引号存在以下问题:
单引号
str='this is a string'
单引号字符串的限制🚫:
- 单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;
- 单引号字符串不能出现单独一个单引号(对单引号使用转义符后也不行),但可成对出现,作为字符串拼接使用;
双引号
双引号的优点:
- 双引号可以有变量;
- 双引号可以出现转义符;
拼接字符串
your_name="runoob"
# 使用双引号拼接
greeting="hello, "$your_name" !"
greeting_1="hello, ${your_name} !"
echo $greeting $greeting_1
# 使用单引号拼接
greeting_2='hello, '$your_name' !'
greeting_3='hello, ${your_name} !'
echo $greeting_2 $greeting_3
字符串长度
string="adcd"
echo ${#string}
提取字符串
以下实例从字符串第 6 个字符开始截取 5 个字符:
string="Hello,World!"
echo ${string:6:5} #从第 6 个字符开始截取 5 个字符
查找字符串
查找字符 o或 r 的位置(哪个字母先出现就计算哪个):
string="Hello,World!"
echo `expr index "$string" or` # 输出 5
2.1.5 环境变量
由操作系统或用户设置的特殊变量,用于配置 Shell 的行为和影响其执行环境;
2.1.6 特殊变量
有一些特殊变量在 Shell 中具有特殊含义:
$0 表示脚本的名称
$1, $2,... 等表示脚本的第一参数、第二参数;
$# 表示传递给脚本的参数数量;
$? 表示上一个命令的退出状态等;

2.2 变量赋值
shell 变量在赋值时等号两边不能紧跟空格;
#正确格式
variable_name=value
#错误格式
variable_name = value
除了显示直接赋值,还可以使用语句给变量赋值,如下:
for file in `ls /etc`
或
for file in $(ls /etc)
以上语句将 /etc 下目录的文件名循环出来。
2.3 使用变量
使用变量只需在变量前添加$variable_name即可,为了帮助解释器识别变量的边界,通常使用${variable_name}的方式获取变量值;
for skill in Ada Coffe Action Java; do
echo "I am good at ${skill}Script"
done
#如果不使用{},则会导致解释器就会把$skillScript当成一个变量(其值为空)
for skill in Ada Coffe Action Java; do
echo "I am good at $skillScript"
done
2.4 只读变量
使用 readonly 命令可以将变量定义为只读变量,只读变量的值不能被改变。
#!/bin/bash
myUrl="https://www.google.com"
readonly myUrl
myUrl="https://www.runoob.com" # /bin/sh: NAME: This variable is read only.
2.5 删除变量
使用 unset 命令可以删除变量。变量被删除后不能再次使用,unset 命令不能删除只读变量
#!/bin/sh
myUrl="https://www.runoob.com"
unset myUrl
echo $myUrl #输出为空
3、传递参数
可以在执行Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为$n,n表示一个数字,如$1表示第一个输入参数,$2表示第二个输入参数;
以下实例我们向脚本传递三个参数,并分别输出,其中 $0 为执行的文件名(包含文件路径)
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
echo "Shell 传递参数实例!";
echo "执行的文件名:$0";
echo "第一个参数为:$1";
echo "第二个参数为:$2";
echo "第三个参数为:$3";
# output
#Shell 传递参数实例!
#执行的文件名:./mk.sh
#第一个参数为:1
#第二个参数为:2
#第三个参数为:3

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
echo "Shell 传递参数实例!";
echo "第一个参数为:$1";
echo "参数个数为:$#";
echo "传递的参数作为一个字符串显示:$*";
# output
#Shell 传递参数实例!
#第一个参数为:1
#参数个数为:3
#传递的参数作为一个字符串显示:1 2 3
$* 与 $@ 区别:
- 相同点:都是引用所有参数。
- 不同点:只有在双引号中体现出来。假设在脚本运行时写了三个参数 1、2、3,则
" * "等价于 “1 2 3”(传递了一个参数),而"@"等价于 “1” “2” “3”(传递了三个参数)。
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
echo "-- \$* 演示 ---"
for i in "$*"; do
echo $i
done
echo "-- \$@ 演示 ---"
for i in "$@"; do
echo $i
done
# output
#-- $* 演示 ---
#1 2 3
#-- $@ 演示 ---
#1
#2
#3
4、基本运算符
4.1 算数运算符
原生bash本身不支持算数运算符,但可以通过其他命令来实现,例如awk和expr,expr最为常见;expr 是一款表达式计算工具,使用它能完成表达式的求值操作;
#!/bin/bash
val=`expr 2 + 2` #表达式与运算符之间要有空格;
#表达式需要被``包含;
echo "两数之和为 : $val"
下表列出了常用的算术运算符,假定变量 a 为 10,变量 b 为 20:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
a=10
b=20
val=`expr $a + $b`
echo "a + b : $val"
val=`expr $a - $b`
echo "a - b : $val"
val=`expr $a \* $b` #乘号(*)前边必须加反斜杠(\)才能实现乘法运算;
echo "a * b : $val"
val=`expr $b / $a`
echo "b / a : $val"
val=`expr $b % $a`
echo "b % a : $val"
if [ $a == $b ]
then
echo "a 等于 b"
fi
if [ $a != $b ]
then
echo "a 不等于 b"
fi
4.2 关系运算符
关系运算符只支持数字,不支持字符串,除非字符串的值是数字
下表列出了常用的关系运算符,假定变量 a 为 10,变量 b 为 20:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
a=10
b=20
if [ $a -eq $b ]
then
echo "$a -eq $b : a 等于 b"
else
echo "$a -eq $b: a 不等于 b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a 不等于 b"
else
echo "$a -ne $b : a 等于 b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a 大于 b"
else
echo "$a -gt $b: a 不大于 b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a 小于 b"
else
echo "$a -lt $b: a 不小于 b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a 大于或等于 b"
else
echo "$a -ge $b: a 小于 b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a 小于或等于 b"
else
echo "$a -le $b: a 大于 b"
fi
4.3 布尔运算符
下表列出了常用的布尔运算符,假定变量 a 为 10,变量 b 为 20:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
a=10
b=20
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a == $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a 小于 100 且 $b 大于 15 : 返回 true"
else
echo "$a 小于 100 且 $b 大于 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a 小于 100 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 100 或 $b 大于 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a 小于 5 或 $b 大于 100 : 返回 true"
else
echo "$a 小于 5 或 $b 大于 100 : 返回 false"
fi
4.4 逻辑运算符
以下介绍 Shell 的逻辑运算符,假定变量 a 为 10,变量 b 为 20:

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
a=10
b=20
if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi
4.5 字符运算符
下表列出了常用的字符串运算符,假定变量 a 为 "abc",变量 b 为 "efg":

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
a="abc"
b="efg"
if [ $a = $b ] #此处==也是正确的
then
echo "$a = $b : a 等于 b"
else
echo "$a = $b: a 不等于 b"
fi
if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ -z $a ]
then
echo "-z $a : 字符串长度为 0"
else
echo "-z $a : 字符串长度不为 0"
fi
if [ -n "$a" ]
then
echo "-n $a : 字符串长度不为 0"
else
echo "-n $a : 字符串长度为 0"
fi
if [ $a ]
then
echo "$a : 字符串不为空"
else
echo "$a : 字符串为空"
fi
4.6 文件测试运算符
文件测试运算符用于检测 Unix 文件的各种属性;属性检测描述如下:

其他检查符:
-S: 判断某文件是否 socket。
-L: 检测文件是否存在并且是一个符号链接

#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
file="/var/www/runoob/test.sh"
if [ -r $file ]
then
echo "文件可读"
else
echo "文件不可读"
fi
if [ -w $file ]
then
echo "文件可写"
else
echo "文件不可写"
fi
if [ -x $file ]
then
echo "文件可执行"
else
echo "文件不可执行"
fi
if [ -f $file ]
then
echo "文件为普通文件"
else
echo "文件为特殊文件"
fi
if [ -d $file ]
then
echo "文件是个目录"
else
echo "文件不是个目录"
fi
if [ -s $file ]
then
echo "文件不为空"
else
echo "文件为空"
fi
if [ -e $file ]
then
echo "文件存在"
else
echo "文件不存在"
fi
4.7 自增与自减运算
Shell 本身没有像 C、C++ 或 Java 那样的 ++ 和 – 操作符,但可以通过其他方式实现相同的功能;
#使用 let 命令
#!/bin/bash
# 初始化变量
num=5
# 自增
let num++
# 自减
let num--
echo $num
#使用 $(( )) 进行算术运算
# 初始化变量
num=5
# 自增
num=$((num + 1))
# 自减
num=$((num - 1))
echo $num
#使用 expr 命令
# 初始化变量
num=5
# 自增
num=$(expr $num + 1) #num=`expr $num + 1`
# 自减
num=$(expr $num + 1) #num=`expr $num - 1`
echo $num
#使用 (( )) 进行算术运算
# 初始化变量
num=5
# 自增
((num++))
# 自减
((num--))
echo $num
5、echo 与print
5.1 echo
#显示换行
echo -e "OK! \n" # -e 开启转义
echo "It is a test"
#显示不换行
echo -e "OK! \c" # -e 开启转义 \c 不换行
echo "It is a test"
5.2 print
printf 中使用格式化字符串,还可以制定字符串的宽度、左右对齐方式等。默认的 printf 不会像 echo 自动添加换行符,我们可以手动添加 \n;
#format-string: 一个格式字符串,它包含普通文本和格式说明符;
#arguments: 用于填充格式说明符的参数列表;
printf format-string [arguments...]
#%s:字符串
#%d:十进制整数
#%f:浮点数
#%c:字符
#%x:十六进制数
#%o:八进制数
#%b:二进制数
#%e:科学计数法表示的浮点数
6、流程控制
6.1 if … else …
if condition
then
command1
command2
...
commandN
fi
6.2 if else-if else
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
6.3 for循环
for var in item1 item2 ... itemN
do
command1
command2
...
commandN
done
6.4 while 语句
while condition
do
command
done
6.5 无限循环
# 方法1
while :
do
command
done
# 方法2
while true
do
command
done
# 方法3
for (( ; ; ))
6.6 until 循环
until 循环执行一系列命令直至条件为 true 时停止,
until condition
do
command
done
condition 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。
6.7 case … esac
case ... esac 为多选择语句,与其他语言中的 switch ... case 语句类似,是一种多分支选择结构,每个 case 分支用右圆括号开始,用两个分号 ;; 表示 break,即执行结束,跳出整个 case ... esac 语句,esac(就是 case 反过来)作为结束标记。case ... esac 语法格式如下:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
#example 1
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
#example 2
#!/bin/sh
site="runoob"
case "$site" in
"runoob") echo "菜鸟教程"
;;
"google") echo "Google 搜索"
;;
"taobao") echo "淘宝网"
;;
esac
6.8 跳出循环
在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,Shell 使用两个命令来实现该功能:break 和 continue。
6.8.1 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
6.8.2 continue
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
7、函数
7.1 函数定义
shell中函数的定义格式如下:
[ function ] funname [()]
{
action;
[return int;]
}
说明:
- 可以带
function fun()定义,也可以直接fun()定义,不带任何参数; - 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n(0-255);
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
demoFun(){
echo "这是我的第一个 shell 函数!"
}
echo "-----函数开始执行-----"
demoFun
echo "-----函数执行完毕-----"
7.2 return 返回值
下面定义一个带有 return 语句的函数:
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
7.3 函数参数
在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数;
#!/bin/bash
# author:菜鸟教程
# url:www.runoob.com
funWithParam(){
echo "第一个参数为 $1 !"
echo "第二个参数为 $2 !"
echo "第三个参数为 $3 !"
echo "参数总数有 $# 个!"
echo "作为一个字符串输出所有参数 $* !"
}
funWithParam 1 2 3
#output
#第一个参数为 1 !
#第二个参数为 2 !
#第三个参数为 3 !
#参数总数有 3 个!
#作为一个字符串输出所有参数 1 2 3 !
8、文件包含
和其他语言一样,Shell 也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
. filename # 注意点号(.)和文件名中间有一空格
#或
source filename
9、重定向
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null中:
command > dev/null
10、test 命令
test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试:
在shell脚本中,test命令和[(也称为test的内置版本或方括号测试)都用于评估条件表达式。尽管它们在语法上略有不同,但功能上通常是等价的:

file_name="/root/Linux/script/build_test3.sh"
dir_name="/root/Linux/script"
# 使用test命令
if test ! -e "$file_name"; then
echo "File not exists."
else
echo "File does exist."
fi
# 使用[(方括号测试)
if [ -d "$dir_name" ]; then
echo "Directory exists."
else
echo "Directory does not exist."
fi
cd /bin
if test -e ./notFile -o -e ./bash
then
echo '至少有一个文件存在!'
else
echo '两个文件都不存在'
fi
11、测试
#!/bin/bash
if [ ! -e "$OUT/pm-graph/sleepgraph.py" ]; then
echo "ERROR: pm-graph github repo failed to clone"
cleanup
exit
fi
for image in ${KERNEL_IMAGE_NAME}; do
cp /lava-files/$image artifacts/install/.
done
445

被折叠的 条评论
为什么被折叠?



