本文记录的是工作中编写脚本的常用语法整理,比较零散,有错欢迎指正。
一、文件第一行
文件的第一行通常为 #!/bin/bash
或 #!/bin/sh
, #!
用于指定这个脚本文件使用什么解释器来运行,如果在文件第一行指定了解释器,那么直接执行该脚本时就会自动使用文件第一行的解释器来运行该脚本。例如文件test.sh的第一行是 #!/bin/bash
,那么在输入 ./test.sh
后直接回车时(注意,不能直接执行 test.sh
,这种写法会被系统认为你是在执行一个命令,而不是脚本),就会使用 /bin/bash
来运行该脚本。当然,如果输入的是 sh test.sh
,那么第一行的作用就失效了,会使用你手动指定的sh来运行该脚本了。
注: 关于 /bin/bash
和 /bin/sh
的区别,其实 /bin/sh
是 /bin/bash
的软链接,它们对于命令的执行都是一样的。不同之处在于,sh的执行相当于bash的POSIX标准模式,即 /bin/sh
相当于 /bin/bash --posix
,具体的区别体现在sh执行过程中,若出现命令执行失败,则会停止执行脚本,而bash则会跳过失败的命令,继续往后执行。
[root@zjy ~]# ll /bin/sh
lrwxrwxrwx. 1 root root 4 Jan 12 2021 /bin/sh -> bash
[root@zjy ~]# ll /bin/bash
-rwxr-xr-x. 1 root root 1150736 Jan 12 2021 /bin/bash
二、变量
语法: 为 my_var="hello"
,此处定义了一个值为字符串的变量,需要特别注意的是,等号=两边不能有空格。变量的命名只能使用英文字母,数字和下划线,且首个字符不能以数字开头。变量定义之后也可以在其他地方使用同样的语法给它重新赋值,但是注意,不可以使用 $my_var="hi"
这种语法,加花括号是使用变量时才需要的,赋值的时候不可以加花括号。
使用变量: 可以使用两种方式 $my_var
或 ${my_var}
(推荐),第二种加花括号的目的是帮助解释器识别变量边界,使用第二种方式是一种良好的编程习惯。
删除变量: 使用 unset ${my_var}
即可,删除变量后,再次使用变量不会报错,但是不会有任何值, echo "abc${my_var}def"
输出的值为abcdef。
readonly只读变量: 使用 readonly my_var="hello"
就可以将一个变量设置为只读变量, readonly
关键字也可以在变量定义之后再设置,如 readonly my_var
也是可以的,不是必须在变量初始化的时候才可以设置。当一个变量被设置为只读时,它就不可以被重新赋值,也不可以使用命令 unset
删除。
执行以下脚本 sh test.sh
:
#!/bin/sh
readonly my_var="hello"
my_var="hi"
输出为:
[root@zjy ~]# sh test.sh
test.sh: line 3: my_var: readonly variable
三、函数定义
语法如下:
[function] func_name() {
...
[return int]
}
function关键字: 定义一个函数,function关键字是可选的。
语句结束符: 函数中每个语句以换行符作为结束,不用使用分号,一行一句即可,分号通常只是用于连接两个语句。
return关键字: 也是可选的,不指定时自动使用最后一个语句的运行结果作为返回值。
函数返回值: 其实无论是否使用return指定函数返回值,本质上,函数的返回值都是此函数最后一条语句的运行结果。shell中一条语句的运行结果为整数,0表示执行成功,其他数字表示失败。获取函数返回值使用 $?
,$?
的本质是代表它上一条语句的执行结果,所以函数执行之后想要拿到其返回值, $?
和函数执行语句之间就不能有其他语句的执行。
函数传参: 格式为 func_name var1 var2 var3 ...
,在函数中获取参数时使用 $1
或 ${1}
的形式获取对应第一个参数,需要注意的是,获取第十个及以上参数时,就只能使用大括号的格式获取了, $10
是无法获取第十个参数的。
#!/bin/sh
function hello() {
echo "Hello Shell"
# 函数参数以$1或${1}、$2或${2}等方式获取对应的第一个、第二个等参数,
# 如果参数个数大于9,那么从第十个开始,就必须使用${10}的格式了,不能使用$10的格式了
echo 1
echo ${2}
return 0
}
# 函数执行直接将函数名当做命令执行即可,函数参数以空格分隔分别传入
hello var1 var2
# 函数执行结果需要在函数执行之后下一行立马获取,不能有其他语句在这中间去执行,
# 否则$?拿到的就是它上一条语句的执行结果,而不是函数的执行结果了
result=$?
echo ${result}
Hello Shell
var1
var2
0
local变量: local变量就是函数内的局部变量,只能用在函数中,如果在函数之外使用local定义变量,会报错并提示 local: can only be used in a function
。当然,函数内定义的local变量,在函数外就无法使用了,使用时不会报错,只是会拿到一个空的值。
四、if判断
语法如下:
# 单if语句
if condition
then
command
...
fi
# if...else...语句
if condition
then
command
...
else
command
...
fi
# if...elif...else...语句
if condition
then
command
...
elif conditin
then
command
...
else
command
...
fi
分号“;”的使用: 分号并不是语句结束符,它的作用是连接不同的语句,比如想要一个if语句在一行之内编写,可以这样 if condition; then command; fi
,这种使用分号连接多条语句的用法通常用在终端客户端或者临时一次性执行多条语句的时候。在使用if语句的时候,为了编写的shell脚本代码更简洁易懂,我们通常会使用分号将 then
连接在上一行,如:
if condition; then
command
...
elif conditin; then
command
...
else
command
...
fi
五、括号( ) 与 双括号 (( ))
括号( )
单括号 (...)
常用的用法有两种,一种是用于shell中的数组,一种是获取命令执行后的结果。
1. 数组: 括号 ( )
最直观的使用当然是数组,因为shell中数组的定义就是 array_name=(value1 value2 ...)
,这里只列一些基础的使用示例:
#!/bin/sh
# 数组定义
my_array=("a" "b" "c")
# 根据下标获取数组元素
echo ${my_array[0]}
echo ${my_array[1]}
# 获取数组所有元素
echo ${my_array[*]}
# 获取数组长度
echo ${#my_array[*]}
# 通过下标直接定义数组
new_array[0]="D"
new_array[1]="E"
new_array[2]="F"
# 打印数组所有元素
echo ${new_array[*]}
输出如下:
a
b
a b c
3
D E F
2. 执行命令: 括号 ( )
另外一种非常常用的用法是使用语法 $(...)
执行命令,然后获取命令的执行结果。
# 执行单个命令
now_date=$(date)
echo ${now_date}
# 多个命令一起执行,获取最后的执行结果
current_path=$(cd $(dirname ${0});pwd)
echo ${current_path}
输出:
Fri Nov 25 01:23:55 CST 2022
/root/shell_test
双括号(( ))
需要特别注意,双括号 (( ))
是用于整数运算的,不能用于其他类型数据的运算,并且 (( ))
中使用的变量可以直接使用名称,而不用加 $
符号。常用的用法有两种,一种是获取整数计算表达式的值,另一种就是作为if语句的判断表达式。
1. 获取整数计算值: 可以使用 $(( ... ))
的方式获取整数计算表达式的值。示例:
#!/bin/sh
a=2
b=3
# 直接使用变量名称进行计算
c=$((a+b))
# 输出结果:5
echo ${c}
2. if条件判断: 作为条件判断时,同样可以使用 +、-、*、/、%、==、!=
等算术运算符,如果想要多个表达式一起判断,也可以使用 &&、||
逻辑运算符。示例如下:
#!/bin/sh
a=2
b=3
c=6
if ((a<b && a+b<c)); then
echo "YES"
fi
六、中括号[ ] 与 双中括号[[ ]]
[ ]
和 [[ ]]
这两者最常用的用法就是用作条件判断,用作条件判断时, 推荐使用双中括号 [[ ]]
的方式 。需要特别注意,使用时符号边界处和操作符两边都必须要要有空格,如 [[ a > b ]]
。这里列出一些使用它们时的不同之处(了解之后就知道为什么推荐使用 [[ ]]
了):
符号性质
[ ]
是bash的内置命令,而 [[ ]]
是shell编程语言的关键字,它相当于是在 [ ]
命令的基础上进行了扩展, [ ]
可以做到的事情, [[ ]]
几乎都可以做到。
变量引用
[ ]
中使用变量必须加上 $
符号来引用,否则会报错,而 [[ ]]
不仅兼容 $
引用的方式,对于数字变量的比较,还可以直接使用变量名进行判断,当然如果变量的值是字符串的话,还是需要使用 $
进行引用。
a=2
b=3
# 直接使用变量名进行比较判断
if [[ a < b ]]; then
echo "YES"
fi
关系运算符
对于数字变量的比较,想要使用 “小于”、“大于”等关系运算, [ ]
只能使用 -lt
、 -gt
等字母形式的表示方式,而 [[ ]]
不仅兼容这种方式,还是可以直接使用 <
、 >
等符号的形式。
逻辑运算符
想要使用与、或等逻辑运算关系, [ ]
只能使用 -a
、 -o
等字母的形式,而 [[ ]]
则可以使用 &&
、 ||
等符号表示的方式,但是与前面几种运算符不同, [[ ]]
中不支持使用 -a
等方式的运算。
a=2
b=3
c=6
# 使用$(( ))获取整数运算的结果,再使用&&做逻辑与运算
if [[ a < b && $((a + b)) < c ]]; then
echo "YES"
fi
# 使用-a做逻辑与运算
if [ ${a} -lt ${b} -a $((${a} + ${b})) -lt ${c} ]; then
echo "YES"
fi
七、字符串运算
对于字符串的使用,需要加上 $
进行引用,特别是在 [[ ]]
中作为条件判断时没有使用 $
的话,无法进行正确的判断。
判断两个字符串是否相同
在 [[ ]]
使用 =
、 ==
、 !=
判断两个字符串是否相等,如果不确定变量的数据类型,但是想要将其转换为字符串再进行比较,可以在变量外边包裹一个双引号再进行判断。
a="abc"
b="bcd"
c="abc"
# 使用=判断字符串是否相等
if [[ ${a} = ${c} ]]; then
echo "YES-a"
fi
# 使用==判断字符串是否相等
if [[ ${a} == ${c} ]]; then
echo "YES-c"
fi
# 使用!=判断字符串是否不等
if [[ ${a} != ${b} ]]; then
echo "YES-b"
fi
d=333
e="333"
# 可以使用双引号将变量包裹起来,将其转换为字符串进行比较判断
if [[ "${d}" == "${e}" ]]; then
echo "YES-d"
fi
判断一个字符串是否为空(或长度为0)
可以直接对引用的字符串进行判断 if [[ ${var} ]]
,为空就是false,不为空就是true,当然,也可以使用 -z
和 -n
显式的判断字符串是否为空。
a="abc"
b=""
# 使用-z判断字符串是否为空,为空返回true
if [[ -z ${b} ]]; then
echo "YES-b"
fi
# 使用-n判断字符串是否不为空,不为空返回true
if [[ -n ${a} ]]; then
echo "YES-a"
fi
# 直接判断引用的字符串是否不为空,不为空返回true
if [[ ${a} ]]; then
echo "YES-abc"
fi
字符串拼接
拼接字符串最简单的方式就是在外面用一个双引号包裹,里面填充变量值即可。
a="aaa"
b="bbb"
c="ccc"
echo "${a}111${b}222${c}"
标签:bin,...,Shell,变量,笔记,echo,语法,sh,使用
From: https://www.cnblogs.com/guyuyun/p/16891126.html