Bash学习要点
在Linux系统中,默认使用bash进行系统的交互。bash入门很简单,越用越难、越繁琐,然后惊奇发现bash原来可以构建一切,疯狂尝试,最后终于回归理性,将bash作为与OS交互的工具、作为200行左右的shell脚本执行引擎。如果工作规模超过200行,建议使用通用的编程语言。
具体问题,官方文档、搜索引擎是一个好的工具。
基本交互
输出内容
- 输出到终端
echo "hello bash" # 这里是注释,如果单行,最后的分号;可省略
- 输出到文件
echo "hello bash" > filename.txt #filename.txt可以是有权限的任意位置的文件路径,覆盖写
echo "hello bash" >> filename.txt # 追加到filename.txt文件中
输入内容
- 从终端输入
read name
echo "$name It is a test"
- 从文件输入
content=$(<filename.txt)
content=$(cat filename.txt)
content=`cat filename.txt`
- 逐行读取文件内容
while read line
do
echo $line
done < filename.txt # 待读取的文件
cat filename.txt | while read line
do
echo $line
done
for line in `cat filename.txt`
do
echo $line
done
变量
创建
定义变量方法为
var_name=var_value #这是一个注释,等号=两侧不能有空格
注意等号"="两侧不能有空格。
读取
变量定义完成后,通过在变量名称前加'$'符号进行引用。
echo $var_name #打印变量var_name的值
如果变量与别的字符串进行组合产生歧义,使用{}
包括变量。
echo pre_${var_name}_sur
数组
创建
- 方法1
array_name=(value0 value1 value2)
- 方法2
array_name[0]=value0
array_name[1]=value1
array_name[2]=value2
读取
- 读取指定下标n的元素
${array_name[n]} # 获取下标n指定的元素,如果不存在,返回空
- 读取全部元素
${array_name[@]} # 使用@符号代替数字,获取全部元素
获取数组信息
- 数组长度
length=${#array_name[@]}
或者
length=${#array_name[*]}
条件判断
逻辑关系判断
符号 | 说明,预设a=10; b=20 |
---|---|
! |
非运算,[ ! flase ] 返回true |
-o |
或运算,[ $a -lt 20 -o $b -gt 100 ] 返回true |
|| |
同-o |
-a |
与运算,[ $a -lt 20 -a $b -gt 100 ] 返回false |
&& |
同-a |
数学关系判断
根据下表中的符号进行数学关系判断,包裹在[ ]中,注意中括号两侧的空格,判断的两个元素在符号的两侧,基本形式为
[ $value1 -op $value2 ] # 分号根据实际需要增删
文件相关判断
符号 | 说明,file是路径 |
---|---|
-e file |
检测file是否存在 |
-f file |
检测file是否是普通文件 |
-d file |
检测file是否是目录 |
-r file |
检测file是否可读 |
-w file |
检测file是否可写 |
-x file |
检测file是否可执行 |
-s file |
检测file是否为空 |
符号 | 说明,预设a=10; b=20 |
---|---|
-eq |
判断两侧元素是否相等,[ $a -eq $b ] 返回false |
-ne |
判断两侧元素是否不相等,[ $a -ne $b ] 返回true |
-gt |
判断左侧元素是否大于右侧的元素,[ $a -gt $b ] 返回false |
-ge |
判断左侧的元素是否大于等于右侧的元素,[ $a -ge $b ] 返回false |
-lt |
判断左侧的元素是否小于右侧的元素,[ $a -le $b ] 返回true |
-le |
判断左侧的元素是否小于等于右侧的元素,[ $a -le $b ] 返回true |
代码流程控制
if判断
- 形式1
if condition1; then
echo "condition1 branch"
fi
- 形式2
if condition1; then
echo "condition1 branch"
else
echo "other branch"
fi
- 形式3
if condition1; then
echo "condition1 branch"
elif condition2; then
echo "condition2 branch"
else
echo "other branch"
fi
case选择
case some_value in # case开始
pattern1) # 分支的条件
command1 # 分支的执行语句
;; # 分支结束标志
pattern2)
command2
;;
*) # 通配分支,即任何条件都满足的分支
;;
esac # case结束
每个分支最后一个语句有三种符号组合
符号 | 说明 |
---|---|
;; |
两个分号,表示执行完当前分支后跳出case块 |
;& |
分号和与号,表示执行完当前分支后,强制执行下一个分支 |
;;& |
两个分号和一个与号,表示执行完当分支后,判断下一个分支条件,是否继续执行 |
for循环
依次取for列表中的每一个元素,并执行后续的语句块。
for v in item1 item2 item3 ; do
echo $v
done
while循环
循环执行while块的操作,根据指定的条件判断是否跳出循环。
while condition1; do
command1
done
数学运算
bash原生不支持数学运算,可通过expr
来实现。
val=`expr 2 + 2` #注意必须有空格,且被``(键盘左上角)符号包裹
echo $val # val为4
符号 | 说明,预设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="abc";b="efg" |
---|---|
= |
判断两个字符串是否相等,[ $a = $b ] ,返回false |
!= |
判断两个字符串是否不相等,[ $a != $b ] ,返回true |
-z |
检测字符串是否为空,[ -z $a ] ,返回false |
-n |
检测字符串是否不为空,[ -n $a ] ,返回true |
str |
检测字符串是否不为空,[ $a ] ,返回true,同上 |
获取参数信息
大部分shell文件在运行时需要提供运行的参数,这里就讲解下如何获取传递的参数。
符号 | 说明 |
---|---|
$# |
获取传递给shell文件的参数的个数 |
$* |
获取当前传递给shell文件的所有参数组成的字符串,如果以"$*"形式(即被双引号包裹)使用,则返回整体的字符串 |
$@ |
获取当前传递给shell文件的所有参数组成的字符串,如果以"$@"形式(即被双引号包裹)使用,依旧返回单个形式的字符串列表 |
$n |
第n个参数的值 |
获取shell运行进程相关信息
符号 | 说明 |
---|---|
$$ |
获取当前运行的进程ID号 |
$! |
后台运行的最后一个进程ID号 |
$- |
显示当前shell进程的选项 |
$? |
显示最近命令的退出状态,0表示正常,否则表示异常 |
自定义函数
自定义函数的格式为
[ function ] funname [()]
{
action;
[return int;]
}
例如下面例子
funWithReturn(){
echo "这个函数会对输入的两个数字进行相加运算..."
echo "输入第一个数字: "
read aNum
echo "输入第二个数字: "
read anotherNum
echo "两个数字分别为 $aNum 和 $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
echo "输入的两个数字之和为 $? !"
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
shell文件引用
shell中可以引用别的文件,使用别的shell文件中的功能。
. filename.sh # 注意点号(.)和文件名中间有一空格
source filename
filename.sh文件的内容在当前代码点被执行一边。