shell语法不多,不算难,这里作为一项硬技能,自己总结一下。主体内容来自于菜鸟教程。
shell变量
定义变量时,变量名和等号之间不能有空格
1
your_name="runoob.com"
使用变量加美元符号,变量名外面的花括号从语法层面上是可选的,加不加都行。不过加上可以帮助解释器识别变量的边界。
1
2
echo $your_name # "runoob.com"
echo ${your_name} # "runoob.com"
数组
Bash Shell 只支持一维数组(不支持多维数组),数组元素的下标由 0 开始,Shell 数组用括号来表示,元素用”空格”符号分割开。
定义数组:
1
2
3
4
array=(value1 value2 ... valuen)
# example
array=(1 2 3 4)
索引数组:
1
${array[index]}
获取数组的所有元素:
1
2
3
4
5
6
${array[@]}
# demo
array=(1 2 3 4)
echo ${array} # 1
echo ${array[@]} # 1 2 3 4
获取数组的长度:
1
${#array[@]}
遍历数组:
1
2
3
for v in ${array[@]}; do
echo "${v}";
done
字符串
定义字符串可以用单引号,也可以用双引号。
1
2
str1='string1'
str2="string2"
拼接字符串,写在一起即可
1
2
str3=${str1}${str2}
echo str3 # string1string2
获取字符串长度
1
echo ${#str1}
提取子字符串,语法为${variable:offset:length}
1
2
string="welcome"
echo ${string:1:4} # 从index为1的位置开始,读取4个元素。输出 elco
字符串运算符
1
2
3
4
5
6
a="abc"
b="efg"
[ $a = $b ] # 判断是否相等,返回 false。
[ $a != $b ] # 判断是否不等,返回 true。
# 更多运算符参见https://www.runoob.com/linux/linux-shell-basic-operators.html
向shell脚本传入参数
使用$
获取传入的参数。$1
表示第一个参数,$2
表示第二个参数… ($0
是执行的bash脚本路径)
示例:
建立test.sh
如下
1
2
3
4
#!/bin/bash
echo "脚本路径: $0"
echo "第一个参数: $1"
echo "第二个参数: $2"
执行
1
./test.sh 1 2
得到输出:
1
2
3
脚本路径: path/to/test.sh
第一个参数: 1
第二个参数: 2
获取更多传入参数的信息,参见菜鸟教程-Shell 传递参数
基本运算符
算术运算符
原生bash不支持简单的数学运算,可借助expr
实现。
1
2
3
4
5
6
a=2
b=2
echo "两数之和为 : `expr $a + $b`"
echo "两数之差为 : `expr $a - $b`"
echo "两数之积为 : `expr $a \* $b`" # 注意,单纯的*会报语法错误,要用\*
echo "两数之积为 : `expr $a / $b`"
需要注意:
- 完整的表达式要被 ` 包含,注意这个字符不是常用的单引号,是在 Esc 键下边的反引号。
- 表达式和运算符之间要有空格
关系运算符
布尔运算符
let语句
let 命令是 BASH 中用于计算的工具,用于执行一个或多个表达式,变量计算中不需要加上$
来表示变量。菜鸟教程-Linux let 命令
示例
1
2
3
4
a=1
b=2
let c=a+b # 不用加$
echo $c # 3
shell流程控制
分支
if
1
2
3
4
5
6
if condition
then
command1
...
commandN
fi
if else
1
2
3
4
5
6
7
8
if condition
then
command1
...
commandN
else
command
fi
if else if
1
2
3
4
5
6
7
8
9
if condition1
then
command1
elif condition2
then
command2
else
commandN
fi
使用((...))
作为判断语句。
示例
1
2
3
4
if (( $a == $b ))
then
echo "a 等于 b"
fi
for循环
1
2
3
4
5
6
for var in item1 ... itemN
do
command1
...
commandn
done
写成一行
1
for var in item1 item2 ... itemN; do command1; ...; commandn; done;
示例
1
2
3
4
for loop in 1 2 3 4 5
do
echo "The value is: $loop"
done
while循环
1
2
3
4
while condition
do
command
done
示例
1
2
3
4
5
6
val=1
while(( $val<=5 ))
do
echo $val
let val++
done
break和continue
break
和continue
作为一条command出现在bash脚本中。其含义与其他语言一致。
shell函数
基本格式
1
2
3
4
5
funname()
{
...
[return sth;]
}
- 可以向函数传入参数,参见下面的示例
- 在函数体内部,通过
$n
的形式来获取传入的参数值。$1
表示第一个参数,$2
表示第二个参数… ($0
是执行的bash脚本路径) - 如果函数有返回值,则函数返回值在调用该函数后通过使用
$?
获得
示例
1
2
3
4
5
6
7
8
9
add(){
echo "第一个参数为 $1"
echo "第二个参数为 $2"
let val=$1+$2
return $val
}
add 1 2
echo "输入的两个数字之和为 $?" # 3
shell输出
可用echo
和printf
方法。printf
比较类似C语言中的printf
,支持格式化输出。
参见 菜鸟教程-Shell echo命令 和 菜鸟教程-Shell printf 命令。
shell 输入输出重定向
大多数 UNIX 系统命令从你的终端接受输入并将所产生的输出发送回到您的终端。一个命令通常从一个叫标准输入的地方读取输入,默认情况下,这恰好是你的终端。同样,一个命令通常将其输出写入到标准输出,默认情况下,这也是你的终端。菜鸟教程-Shell 输入/输出重定向
将输出重定向到 file (file已经存在的内容将被清空替代)
1
command > file
将输出重定向到 file (在file结尾追加)
1
command >> file
将输入重定向到 file
1
command < file
示例
输入重定向:
1
2
3
# in.txt
1
2
1
2
3
4
5
6
7
8
9
10
11
12
# demo.sh
add(){
read a
echo "第一个参数为 $a"
read b
echo "第二个参数为 $b"
let val=$a+$b
return $val
}
add
echo "输入的两个数字之和为 $?"
执行
1
2
bash ./str_demo.sh < in.txt
# 从in.txt读取输入,在终端输出结果
输出重定向:
1
2
3
4
5
6
7
8
9
10
# demo.sh
add(){
echo "第一个参数为 $1"
echo "第二个参数为 $2"
let val=$1+$2
return $val
}
add 1 2
echo "输入的两个数字之和为 $?" # 3
执行
1
2
bash ./str_demo.sh > out.txt
# 输出将写入out.txt,而不显示在终端
当然,也可以选择性地把部分语句重定向,如
1
2
3
4
5
6
7
8
9
10
# demo.sh
add(){
echo "第一个参数为 $1"
echo "第二个参数为 $2"
let val=$1+$2
return $val
}
add 1 2
echo "输入的两个数字之和为 $?" > out.txt
执行
1
2
bash ./str_demo.sh
# 只会把最后一句的输出重定向到out.txt
其他
Q1
加入现在有一个demo.sh
文件,使用
bash ./demo.sh
sh ./demo.sh
./demo.sh
这三者的区别?
答:TODO。参考https://stackoverflow.com/a/20616103/10096987