关于执行结果,以及检测存在性,返回值为0表示正常,返回值为非0表示不正常。这个与正常逻辑相反,需要注意。
1. 前置说明
shell脚本是linux系统中的一个可执行文件,它可以用来批量执行linux命令,比手动输入大量命令要高。
1.1 创建shell脚本
创建shell脚本有几个必须点:
-
文件必须以
.sh
结尾 -
文件的开头必须加上
#! /biin/bash
,指明脚本解释器cd ~ vim myshell.sh
1.2 执行shell脚本
shell脚本的执行:
-
方式一:使用
sh
或bash
命令sh myshell.sh # 等价于 bash myshell.sh
bash 是 sh 的超集
-
方式二:授予文件可执行权限,这样可以直接输入文件名运行文件
# chmod a+x myshell.sh chmod +x myshell.sh # 为当前用户增加对该文件权限 myshell.sh
-
方式三:使用
source
或.
命令source myshell.sh # 等价于 . myshell.sh
sh
vssource
:- 相同:都会执行脚本
- 区别:使用
source
执行的脚本会修改父环境的变量,主要表现为调用的脚本出现了与父环境中相同的变量,会将其值替换。而sh
脚本不能修改其父Shell的环境。
1.3 调试shell脚本
-
方式一:在执行脚本时加上
-x
:sh -x myshell.sh
(未授权)-x myshell.sh
(已授权)
-
方式二:在shell脚本中的开头设置
set -x
,再直接执行脚本注意:使用
set -e
可以告诉shell,如果一个命令的退出状态是非零值,则退出shell。这通常用来在脚本中处理错误。如果一个命令失败了(即返回非零退出状态),脚本将立即停止执行。例如,你有以下的shell脚本:
#!/bin/bash set -ex echo "This is a test" non_existent_command echo "This will not be printed"
在这个脚本中,
non_existent_command
是一个不存在的命令,所以它会返回一个非零的退出状态。因为我们使用了-e
选项,所以脚本在这条命令失败后将停止执行,echo "This will not be printed"
这一行将不会被执行。因为我们使用了
-x
选项,所以脚本在执行每一条命令前都会先将命令本身打印出来。所以,如果你运行这个脚本,你将看到类似以下的输出:+ echo 'This is a test' This is a test + non_existent_command ./script.sh: line 7: non_existent_command: command not found
1.4 字符冲突
通过下面可以知道$
字符可以用来获取变量值,但是当我们要打印$
符号怎么办?
使用\
转义。其他字符冲突也是这样处理。
#! /bin/bash
money=100
echo "我有\$${money}元" # 输出:我有$100元
2. 变量
2.1 创建&使用变量
-
创建变量:和Java一样,
=
左边是变量名,右边是变量值。注意事项:
- 变量名首字符必须为字母,名字只能用字母、数字、下滑线,不要用bash关键字。非法的名字:8var、var-8
- 变量名=值,等号两边不能有空格。
- 值只有字符串类型,值可以用单引号、可以用双引号,也可以都不用。但是值中有空格或特殊字符必须需要用双引号或单引号引起来。
#! /bin/bash name="zhansgan" age=18 echo $name # 输出:zhangsan echo "${name}目前${age}岁!" # 输出:zhangsan目前18岁!
-
使用变量:
$变量名
或${变量名}
形式获取变量值。一般首先使用$变量名
,当存在歧义没有达到理想效果时使用${变量名}
方式,获取数组值必须用后者。注意:变量取值不能嵌套,比如:
year=${$3:0:4} # 这样会报错,因为不允许${}里面嵌套$
-
判断变量的值的是否为空。linux变量值都是字符串,没有其他类型。所以其本质上判断变量值是否为空字符串。
-z
是检查变量是否为空。如果变量为空,那么-z条件为真。
-n
是检查变量是否非空。如果变量非空,那么-n条件为真。if [[ -z "${var}" ]]; then echo "var is empty" fi
if [[ -n "${var}" ]]; then echo "var is not empty" fi
2.2 位置变量
-
如果要想向shell脚本里传入参数,可以在运行shell脚本时携带参数。在shell脚本内可以通过一些符号获取传递的值:
-
$0
或${BASH_SOURCE[0]}
:脚本的名称 -
$1
:脚本的第一个参数,$2
是第二个参数,以此类推注意:使用
shift N
命令可以将参数整体左移。这个命令将每个位置参数向左移动N
个位置。例如,$3
的值移动到$2
,$2
的值移动到$1
。同时,$1
的值将被丢弃,原来$N+1
的值将被移动到$N
,以此类推。#!/bin/bash echo "Parameter 1 before shift: $1" echo "Parameter 2 before shift: $2" shift 1 echo "Parameter 1 after shift: $1" echo "Parameter 2 after shift: $2"
-
$#
:传入脚本的参数个数 -
$*
:传入的所有参数拼接为一个字符串后返回#! /bin/bash # 判断当前目录下的所有文件,哪些是文件,哪些不是文件 arr=(`ls ./`) for file in ${arr[*]} do if [ -f file ];then echo "$file is a file" else echo "$file is not a file" if dome
-
$@
:传入的每个参数是一个字符串 -
$?
:上一条命令执行是否成功,0表示执行成功,非0表示执行失败$(命令)
可以获取命令的执行结果
-
$$
:当前进程的id
比如:有 a.sh 脚本,内容如下
#! /bin/bash echo $0 echo $1 echo $2 echo $# echo $* echo $@ echo $?
-
-
判断对应的位置变量是否有值,可借助
-z
或-n
命令。
-z
是检查变量是否为空。
-n
是检查变量是否非空。if [ -z "$1" ]; then echo "variable is empty" fi
2.3 引号与变量
- 单引号:里面的所有字符都是普通字符,不能够获取变量值。单引号内的
${变量名}
会无效。 - 双引号:会保留变量特性。可以使用
${变量名}
获取变量值。#! /bin/bash name="zhansan" echo '$name' # 输出:$name echo "$name" # 输出:zhangsan
倒引号
或$()
:引起来的命令将会被执行,执行后的结果作为这个表达式的值
[root@host ~]$ str=`echo "hello"` [root@host ~]$ echo $str hello [root@host ~]$ str2=$(echo 'hello') [root@host ~]$ echo $str2 hello [root@host ~]$
2.4 变量生命周期
-
普通变量只会在当前文件生效,该变量不会被传递给子shell。假设有text.sh文件:
#!/bin/bash # HOME变量只会在当前文件生效,不会在csv.sh文件中生效 HOME=/usr/zhangsan sh csv.sh
-
能够传递给子文件的变量。前面加上
export
关键字:#!/bin/bash # HOME变量不仅在当前文件生效,在csv.sh文件中也生效 export HOME=/usr/zhangsan sh csv.sh
-
用户级别的环境变量
- 能够在 当前会话 中的每一个shell脚本中都生效的变量。打开用户目录下的
.bashrc
文件进行编辑,在此脚本里使用export
定义的变量即可在每个shell脚本中生效。因为当你启动一个新的bash shell(即打开一个新的终端窗口)时,它会被自动执行。vim ~/.bashrc
- 能够在 每个会话 中都生效的变量。打开用户目录下的
.bash_profile
文件进行编辑,里面export
定义的变量即可在每个会话中都生效。vim ~/.bash_profile
.bash_profile
文件会调用.bashrc
,保证每次会话都拥有相同的系统变量。一般来说,只需要修改.bashrc
文件即可。
- 能够在 当前会话 中的每一个shell脚本中都生效的变量。打开用户目录下的
-
全局的环境变量:在Unix和Linux系统中,
/etc/profile
文件是一个全局配置脚本,里面使用export
定义的变量会为每个用户都生效,常用来定义JAVA_HOME
这类软件变量。当用户登录时,该脚本就会运行。需要注意的是,对/etc/profile
的修改需要管理员权限。
2.5 系统变量
(1) PATH
PATH 是一个环境变量,用于指定系统在哪些目录下搜索可执行文件。通常在~/.bashrc
或~/.bash_profile
文件中使用,用来修改环境变量。
比如:~/.bashrc
文件中
export HADOOP_HOME=/home/work/software/hadoop-client/hadoop
export SCALA_HOME=/home/work/software/scala-2.12.7
export SPARK_HOME=/home/work/software/spark-2.4.3.9/
# 记得加上$PATH
export PATH=$PATH:$HADOOP_HOME/bin:$SPARK_HOME/bin:$SCALA_HOME/bin:$YARN_HOME/bin:${JAVA_HOME}/bin:${MAVEN_HOME}/bin:${PMCLIENT_HOME}/bin
(2) EXIT
在shell脚本中,如果需要在某个条件满足后让脚本异常结束,可以使用 exit 命令。
exit 命令用于结束当前脚本的执行,它后面可以接一个退出状态码(0-255)。其中,0表示成功,其他值表示出错。如果 exit 命令后面没有指定退出状态码,那么默认使用前一个命令的退出状态码。
例如:
#!/bin/bash
# 运行脚本的用户不是root,那么脚本会打印一条错误消息并退出,退出状态码是1。
if [ $(whoami) != 'root' ]; then
echo "You must be root to run this script."
exit 1
fi
2.6 正则匹配
=~
是一个正则表达式匹配操作符,用于检查一个变量的值是否匹配一个正则表达式。
# 检查第三个参数是否为整数
if ! [[ $3 =~ ^[0-9]+$ ]]; then
echo "Error: $3 is not a number"
exit 1
fi
3. 字符串
3.1 字符串切片
- 字符串切片
- 正向切片
# 下标为正 str='abcdef' sub_str=${str:2:1} # 2是下标(下标从0开始);1是截取长度 echo $sub_str # 输出:c # 下标也可以为负 str="Hello" lastChar=${str: -1} allButLast=${str:0:-1} echo "Last character is: $lastChar" # 输出:Last character is: o echo "All but last character is: $allButLast" # 输出:All but last character is: Hell
- 反向切片:中间的下标用空格代替
str="Hello" echo ${str: -2} # 输出:lo
注意:
${str: -1}
中的空格是必要的,否则Bash会将:-1
解析为默认值的语法,从而报错 - 注意:如果是直接对传入的参数进行切片,则可以省略
$
符号,加上会报错,因为${}
语法不能嵌套。#!/bin/bash year=${3:0:4} # 取传入的第三个参数的前4位 month=${3:4:2} # 取传入的第三个参数的5,6位 day=${3:6:2} # 取传入的第三个参数的7,8位 year=${$3:0:4} # 这样会报错,因为不允许${}里面嵌套$
- 正向切片
4. 运算符
4.1 比较&数值运算
4.1.1 方式一:[ ] 📍 数值比较&字符串比较
- 语法:
[ 比较&运算表达式 ]
注意:整体前后空格,运算符前后空格 - 支持的运算有
- 比较运算(数值比较)
- 比较运算(字符串比较)
注意:这里的
==
,也可以只用单等号=
- 比较运算(数值比较)
- 例子:
- 比较运算(数值比较)的例子:
[root@localhost shell]# [ 1 -eq 1 ] && echo 'ok' ok [root@localhost shell]# [ 1 -lt 0 ] && echo 'ok' [root@localhost shell]# [ 1 -lt 2 ] && echo 'ok' ok # 没有空格隔开,报错 [root@localhost shell]# [ 1 -lt 2] && echo 'ok' -bash: [: 缺少 ] # 变量替换也可以 [root@localhost shell]# a=1 [root@localhost shell]# [ $a -lt 2 ] && echo 'ok' ok [root@localhost shell]#
- 比较运算(字符串比较)的例子:
[root@localhost shell]# [ "aaa" == "aaa" ] && echo 'ok' ok [root@localhost shell]# [root@localhost shell]# [ "aaa" != "bbb" ] && echo 'ok' ok # 字符串判空 [root@localhost shell]# s=aaa # 字符串非空 [root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok' [root@localhost shell]# # 字符串为空 [root@localhost shell]# s="" [root@localhost shell]# [ "${s}x" == "x" ] && echo 'ok' ok
- 比较运算(数值比较)的例子:
4.1.3 方式二:(()) 📌 只可用于数值比较
-
语法:
((数字比较 或 运算表达式))
注意:整体前后不需要空格,运算符前后空格 -
支持的运算有:
- 比较:
==
、!=
、<
、<=
- 数值运算:
加减乘除
、取模
、自加
【a++或++a】、+=
注意:无论是比较还是数值运算,只支持数字,不支持字符串,因为字符串会自动转为true,两个字符串比较的结果永远为true
flag='h' if $(($flag == 'd' )); then echo "Flag is d" else echo "Flag is not d" fi # 输出:Flag is d ```
- 比较:
-
加上
$
可取运算后的值$((数值运算))
。 -
例子:
#! /bin/bash a=10 b=20 echo "$((a+b))" # 输出:30 a=10 echo "$((a%2))" # 删除:0 a=10 echo "$((a++))" # 输出:10,此时a=11 a=10 echo "$((++a))" # 输出:11,此时a=11 a=10 echo "$((a!=2))" # 输出:11,此时a=11 a=10 echo "$((a==2))" # 输出:11,此时a=11 a=10 echo "$((a<=2))" # 输出:0 a=10 echo "$((a<2))" # 输出:0 a=10 echo "$((a+=2))" # 输出:12
4.2 逻辑运算
-
语法:
-
采用
[ ]
进行运算
-
采用
(())
进行运算运算符 说明 示例 ! 非运算 ((! 2 < 1)) && echo ‘ok’ | 或运算 ((1 == 1 | 1 == 2)) && echo ‘ok’ & 与运算 ((1 == 1 & 1 == 2)) && echo ‘ok’ && 短路与 ((1 == 1 && 1 == 2)) && echo ‘ok’ || 短路或 ((1 == 1|| 1 == 2)) && echo ‘ok’
-
-
细节:
&&
和||
有一个非常有用的作用—将多行命令变成一行,这对于平台化的shell脚本执行非常有帮助。通过平台执行shell脚本时,往往限制只能执行一行命令。比如:cd bin && sh run.sh $@
&&
:前面的命令若执行成功(返回0),则执行后面的代码;前面的命令若执行失败(返回非0),则不执行后面的代码。||
:前面的命令若执行成功(返回0),则不执行后面的代码;前面的命令若执行失败(返回非0),则执行后面的代码。
- 通过使用
&&
和||
类似于三元运算符功能[[ -e ${BASH_LOG_FILE} ]] && echo 'file is exist' || echo 'file is not exist.'
4.3 文件运算
语法:[ 运算符 文件相对路径|绝对路径 ]
注意:整体前后空格,运算符前后空格
判断目录是否为空目录:
dir="/path/to/dir" if [ "$(ls -A $dir)" ]; then echo "$dir is not empty" else echo "$dir is empty" fi
[root@localhost shell]# [ -e hello.sh ] && echo 'ok'
ok
[root@localhost shell]# [ -f hello.sh ] && echo 'ok'
ok
[root@localhost shell]# [ -d hello.sh ] && echo 'ok'
[root@localhost shell]#
5. 控制语句
5.1 分支语句
5.1.1 if分支
# 方式一:表达式后面写分号,再写then
if 条件表达式一 ; then
表达式一true时执行这里
elif 条件判断式二 ; then
表达式二true时执行这里
elif 条件判断式三 ; then
表达式三true时执行这里
else
都不成立时,执行这里
fi
# 方式二:表达式后面写不写分号,则必须换行后写thenthen
if 条件表达式一
then 表达式一true时执行这里
elif 条件判断式二
then 表达式二true时执行这里
elif 条件判断式三
then 表达式三true时执行这里
else
都不成立时,执行这里
fi
注意 :
- 最后要以
if
反过来的fi
结尾- 关键字与关键字之间的表达式前后必须空格,所以:关键字
if
、elif
后面必须接空格,then
的前面必须接空格否则报错。
例子:
[root@localhost shell]# vim test.sh
#! /bin/bash
cmd=$1
if [ $cmd == "start" ]
then echo "start"
elif [ $cmd == "stop" ]
then echo "stop"
elif [ $cmd == "restart" ]
then echo "restart"
else
echo "other"
fi
[root@localhost shell]# sh test.sh 123 # 输出:other
5.1.2 模式匹配
case $var in
模式1)
代码块1
;;
模式2)
代码块2
;;
模式3)
代码块3
;;
*)
代码块4
;;
esac
注意 :最后要以
case
反过来的esac
结尾
例子:
[root@localhost shell]# vim s6.sh
#! /bin/bash
cmd=$1
case $cmd in
"start") echo "start operation"
;;
"stop") echo "stop operation"
;;
"restart") echo "restart operation"
;;
*) echo "other operation"
;;
esac
5.2 循环语句
5.2.1 for循环
- 语法:
# 方式一:for-each循环 for 循环变量 in 数据列表; do 循环体代码段 done 或者 for 循环变量 in 数据列表 do 循环体代码段 done # 方式二:下标循环 for ((控制变量的初始化;循环的条件;循环控制变量的更新)) do 循环体代码段 done 或者 for ((控制变量的初始化;循环的条件;循环控制变量的更新)); do 循环体代码段 done
- 数据列表
{1..100}
:表示1到100#! /bin/bash for i in {1..10} do echo $i done # 打印1到10
- 结尾必须写上
done
- 关键字
for
后面可以不接空格,但是推荐空格。
- 数据列表
- 例子:
① for-each循环
② 下标循环#! /bin/bash # 判断当前目录下哪些文件是普通文件 arr=(`ls ./`) # 遍历数组的每个元素(文档) for f in ${arr[*]} do # 判断是否是文件 if [ -f $f ]; then echo "$f is file" fi done
#! /bin/bash # 计算1-10内的偶数之和 sum=0 for((i=1;i<=10;i++)) do if [ $((i%2)) -eq 0 ];then sum=$((sum+i)) fi done echo "sum=${sum}" for ((time=start_time; time>end_time; time--)); do date -d "@$time" '+%Y%m%d %H:%M:%S' done
5.2.2 while循环
-
语法:
while ((循环的条件)) do 循环体代码段 done
- 以
done
结束 - 关键字
for
后面可以不接空格,但是推荐空格。
- 以
-
例子
#! /bin/bash i=1 while((i<10)) do ((i++)) done echo "i=$i" # 输出:i=10
6. 函数定义
6.1 没有返回值的函数
#!/bin/bash
fun(){
echo "hello student!"
}
fun # 输入方法名时,调用函数
6.2 有返回值的函数
#!/bin/bash
num1=$1
num2=$2
funandReturn(){
return $(($num1+$num2))
}
funandReturn # 输入函数名,会调用函数
echo "输入的两个数字之和为 $? !" # 通过 $? 获取函数返回值
6.3 定义函数内变量
在Linux中,local
是一个bash shell内建命令,用于在函数中创建局部变量。这些变量只在定义它们的函数及其子进程中可见,而在函数外部则不可见。
function myfunc() {
local myvar="Hello, World!"
echo $myvar
}
myfunc # Prints "Hello, World!"
echo $myvar # Prints nothing because myvar is not defined in this scope
3. 数据结构
3.1 数组
3.1.1 创建数组
-
方式一:直接定义并初始化。
#! /bin/bash arr=("aaa" "bbb" "ccc") arr=("aaa" "bbb" "ccc" )
注意:元素间使用空格或回车,而不是逗号分隔;并且后续可以继续添加元素,并不是静态的。
-
方式二:使用
declare -a
#! /bin/bash # 1. 定义并初始化 declare -a arr=("aaa" "bbb" "ccc") # 2. 先定义,再赋值 declare -a arr arr[0]="aaa" arr[1]="bbb" arr[2]="ccc"
-
搭配for循环,能够将字符串使用默认的
\t
和\n
分割做为一个数组。比如:
#! /bin/bash arr=$(ls -l ./) for x in ${arr[@]}; do echo $x done
输出:
[fenrun@njjs-passport-bigdata00.njjs.baidu.com utils]$ 总用量 20 -rw-rw-r-- 1 fenrun fenrun 8120 10月 10 17:45 AfsToDataframe.scala -rw-rw-r-- 1 fenrun fenrun 3732 9月 9 11:13 HiRobot.scala -rw-rw-r-- 1 fenrun fenrun 66 10月 23 15:43 my.sh -rw-rw-r-- 1 fenrun fenrun 3568 10月 22 10:36 Mytest.scala
3.1.2 使用数组
-
获取数组长度:
${#数组名[*]}
或${#数组名[@]}
。 eg:${#arr[*]}
、${#arr[@]}
-
读取数组元素
- 读取一个元素:
${数组名[下标]}
- 一次读取所有元素:
${数组名[*]}
或${数组名[@]}
- 读取一个元素:
-
给数组元素赋值:
数组名[下标]=值
-
删除数组元素:
unset 数组名[下标]
[root@localhost shell]# arr1=("a1" "b1" "c1") [root@localhost shell]# echo ${arr1[*]} a1 b1 c1 [root@localhost shell]# declare -a arr2=("a2" "b2" "c2") [root@localhost shell]# echo ${arr2[*]} a2 b2 c2 [root@localhost shell]# declare -a arr3 [root@localhost shell]# arr3[0]="a3" [root@localhost shell]# arr3[1]="b3" [root@localhost shell]# arr3[2]="c3" [root@localhost shell]# echo ${arr3[*]} a3 b3 c3 [root@localhost shell]# # 查看数组长度 [root@localhost shell]# echo ${#arr3[*]} 3 # 获取数组第一个元素 [root@localhost shell]# echo ${arr3[0]} a3 # 删除数组第一个元素,数组长度-1 [root@localhost shell]# unset arr3[0] [root@localhost shell]# echo ${#arr3[*]} 2 [root@localhost shell]# echo ${arr3[*]} b3 c3
4. Map
4.1 创建Map
和数组的创建有点类似,但是必须加上declare -a
declare -A arr=([a]="aaa" [b]="bbb" [c]="ccc")
echo "${arr[b]}" # 输出:bbb
declare -A arr=(
[a]="aaa"
[b]="bbb"
[c]="ccc"
)
echo "${arr[b]}" # 输出:bbb
元素间依旧是以
空格
或回车
分隔。
7. 连接数据库
7.1 连接MySQL数据库
# 1. 设置主机信息、账号密码、数据库名
MYSQL_CLIENT=$HOME/.jumbo/bin/mysql # mysql的安装路径/bin/mysql,如果此时机器MySQL已经配置了环境变量,则可以写 MYSQL_CLIENT=mysql
MYSQL_HOST="xxxx"
MYSQL_PORT="xxxx"
MYSQL_USER="xxxx"
MYSQL_PASSWORD="xxxx"
MYSQL_DATABASE="xxxx"
# 2. 登入MySQL
# --skip-column-names 或 -N:输出结果中不显示列名
# -e:表示后续会接一个 SQL 查询语句,这个 SQL 查询语句会被 MySQL 客户端执行
LOGIN_MYSQL="${MYSQL_CLIENT} -h${PALO_HOST} -P${PALO_PORT} -u${PALO_USER} -p${PALO_PASSWORD} -D${PALO_DATABASE} --skip-column-names -e"
LOGIN_MYSQL="${MYSQL_CLIENT} -h${PALO_HOST} -P${PALO_PORT} -u${PALO_USER} -p${PALO_PASSWORD} -D${PALO_DATABASE} -N -e"
# 3. 执行sql
result=${LOGIN_MYSQL} "select * from table"
拉取数据时,如果需要保证数据已经加载完毕,可以采用拉取两次,进行对比的方式,以保证数据拉取完成:
event_day=`date -d "$BASETIME" +'%Y%m%d'`
SQL="select count(1) from xxx where count_date=${event_day};"
i=0
while (( i <= 50 ))
do
((i++))
# 拉取第一次
count_1=$($MYSQL_LOGIN "${SQL}")
echo "get _1 data done, count_1 = ${count_1}"
sleep 5m
# 拉取第二次
count_2=$($MYSQL_LOGIN "${SQL}")
echo "get _2 data done, count_2 = ${count_2}"
sleep 5m
# 两者对比
if ((count_1 > 0 && count_2 > 0 && count_1==count_2));then
echo "month_dump_db_check.sh [query_data_count] date=${event_day} success"
exit ${EXE_SUCCESS}
fi
done
echo "month_dump_db_check.sh [query_data_count] date=${event_day} failed"
exit ${EXE_FAIL}
8. 注意点
8.1 $() 与 ${}的作用
-
${}
- 用来取变量的值。注意可以设置默认值和错误信息
# 1. 设置默认值:${变量名:-默认值},如果变量未设置或为空,返回默认值。 echo "Hello, ${name:-user}" # 如果 name 为空或未设置,输出 "Hello, user" # 2. 设置默认值并赋值给变量:${变量名:=默认值} echo "Hello, ${name:=user}" # 如果 name 为空或未设置,输出 "Hello, user",并将 "user" 赋给 name # 3. 变量未设置,打印错误信息并退出程序:${变量名:?错误信息} echo "Hello, ${name:?name is not set}" # 如果 name 为空或未设置,打印 "name is not set" 并退出
- 还可以用于字符串的截取:
${变量名:偏移量}
和${变量名:偏移量:长度}
name="hello world" echo ${name:6:5} # 输出 "world"
- 还可以用于字符串替换:
${变量名/查找/替换}
name="hello world" echo ${name/world/WORLD} # 输出 "hello WORLD"
- 获取字符串长度:
${#变量名}
name="hello world" echo ${#name} # 输出 "11"
- 用来取变量的值。注意可以设置默认值和错误信息
-
$()
:用来执行命令,并将执行结果作为变量的值。
8.2 exit与return
- 位置不同:exit可以在脚本的任何地方;而return在shell脚本的函数内或者最后一行。
- 作用不用:exit用于结束当前进程;return在函数内时用于结束函数,在shell脚本的最后一行时用于返回脚本中最后一个命令的 exit status
- 细节:当return位于shell脚本的最后一行时,用
sh
执行会报错,得用source
执行。