shell入门
shell 脚本
以 bash 为例
#! /bin/bash
# bash 的shell文件的开头
# 使用 # 可进行单行注释
:<< EOF
以此格式可
进行多行注释
EOF可换成其他字符
EOF
Hello world!
#! /bin/bash
echo "Hello world!"
变量
定义变量
name1='kyleten'
name2="kyleten"
name3=kyleten # 三种定义方式均可
使用变量
使用变量需要加上$
或者${}
,{}
是为了帮助命令解释器识别变量边界
#! /bin/bash
name=kyleten #定义变量name为kyleten
echo $name # 输出kyleten
只读变量
运用readonly
或者declare
将变量变为只读
name=kyleten
readonly name
declare -r name # 两周写法均可
设置为只读变量的值不能被改变
删除变量
unset name # 删除name
删除命令,unset 命令不能删除只读变量
变量类型
运行 shell 时,会同时存在三种变量:
- 局部变量(仅在当前 shell 实例)
- 环境变量
- shell 变量
默认变量
执行 shell 脚本时,可以向脚本传递参数:$0
时文件名(含路径);$1
是第一个参数;$2
是第二个参数;以此类推.
#! /bin/bash
echo $0 # 输出文件名
echo "第一个参数是:"$1
其他相关变量
变量名 | 说明 |
---|---|
$# | 文件传入参数的个数 |
$* | 将所有参数构成以空格隔开的字符串 |
$@ | 将每个参数分别作为字符串输出,中间用空格隔开 |
$$ | 脚本当前运行的进程 ID |
$? | 显示上一条命令的退出状态(exit code),0 表示正常 |
$(command) | 输出command 的正常输出状态(stdout)(可嵌套) |
`command` | 输出command 的 stdout(不可嵌套) |
数组
shell 脚本仅支持一维数组,初始化时无需指明数组大小,下标从 0 开始
定义
数组用小括号表示,每个元素之间用空格隔开
array=(0 kyleten "az")
也可以直接定义某个元素的值
array[0]=0
array[1]=kyleten
array[2]="az"
读取某个元素的值
格式:
$array[index]
array=(0 kyleten "az")
echo ${array[0]}
echo ${array[1]}
echo ${array[2]}
读取整个数组
格式:
${array[@]}
${array[*]} # 两种写法均可
数组长度
格式:
跟字符串类似
${#array[@]}
${#array[*]} # 两种写法均可
read
输入参数,-p
:后跟提示信息;-t
:后面跟秒数,定义输入字符的等待时间
read -p "Please input your name:" -t 30 name # 输入你的名字,等待30秒
echo
用于输出字符串
格式:
echo <string>
echo -e 启用\n 转义
printf
类似于c/c++
中的printf
格式:
printf format-string [arguments...]
test
用于判断文件类型,以及对变量做比较;test
命令用exit code
作为返回结果, 0 表示真,非 0 为假
[]
和test
用法几乎一致,[]
中每一项须用空格隔开,变量最好用双引号括起来,常量用单引号/双引号括起来
例如:
test 2 -lt 3 # 为真,返回值为0
# 也可写成 [ 2 -lt 3 ]
echo $? # 输出上一命令的返回值,为0
文件类型判断
&&
与||
短路原则
在a && b
中, a 为 假 ,则忽略 b
在a || b
中, a 为 真 ,则忽略 b
测试参数 | 表示意义 |
---|---|
-e | 文件是否存在 |
-d | 是否为目录 |
-f | 是否为文件 |
例如:
test -e test1.sh && echo "exist" || echo "not exist"
文件权限判断
格式:
test -r filename # 判断文件是否可读
测试参数 | 表示意义 |
---|---|
-r | 文件是否可读 |
-w | 文件是否可写 |
-x | 文件是否可执行 |
-s | 文件内是否为非空 |
整数间比较
格式:
test $a -eq $b # a 是否等于 b
测试参数 | 表示意义 |
---|---|
-eq | a 是否等于 b |
-ne | a 是否不等于 b |
-gt | a 是否大于 b |
-lt | a 是否小于 b |
-ge | a 是否大于等于 b |
-le | a 是否小于等于 b |
字符串比较
测试参数 | 表示意义 |
---|---|
test -z string | 判断 string 是否为空,如果为空,则返回 true |
test -n string | 判断 string 是否为非空,如果为非空,则返回 true(-n 可省略) |
test str1 == str2 | 判断 str1 是否等于 str2 |
test str1 != str2 | 判断 str1 是否不等于 str2 |
多重条件判定
格式:
test -r filename -a -x filename
测试参数 | 表示意义 |
---|---|
-a | 两条件是否同时成立 |
-o | 两条件是否至少一个成立 |
! | 取反.如 test ! -x file,当 file 不可执行时,返回 true |
判断语句
if
if…then 形式
类似于c/c++
中的if-else
语句
基础(if-then)
if condition
then
语句1
语句2
...
fi
单层(if-else)
if condition
then
语句1
语句2
...
else
语句1
语句2
...
fi
多次(if-elif-elif-else)
if condition
then
语句1
语句2
elif
then
语句1
语句2
elif
then
语句1
语句2
else
语句1
语句2
...
fi
switch
类似于c/c++
中的switch
格式:
case $变量名称 in
值1)
语句1
语句2
...
;; # 类似于c/c++中的break
值2)
语句1
语句2
...
;;
*) # 类似于c/c++中的default
语句1
语句2
...
;;
esac
循环语句
for…in…do…done
格式:
for var in val1 val2 val3
do
语句1
语句2
...
done
for((…;…;…))do…done
格式:
for((expression;condition;expression))
do
语句1
语句2
...
done
while…do…done
格式:
while condition
do
语句1
语句2
...
done
until…do…done
格式:
until condition
do
语句1
语句2
done
break
与c/c++
基本一致,但无法跳出case
语句
continue
与c/c++
完全一致
函数
类似于c/c++
中的函数,但返回值为exit code
,取值为 0-255
格式:
[function]func_name(){ # 可省略[function]
语句1
语句2
...
}
fuc_name
# 调用函数格式
文件重定向
每个进程默认打开 3 个文件描述符
stdin
标准输入,从命令行读取数据,文件描述符为 0stdout
标准输出,从命令行输出数据,文件描述符为 1stderr
标准错误输出,从命令行输出数据,文件描述符为 2
重定向命令 | 说明 |
---|---|
command >file | 将stdout 重定向到file 中 |
command <file | 将stdin 重定向到file 中 |
command >>file | 将stdout 以追加方式重定向到file 中 |
command n >file | 将文件描述符n 重定向到file 中 |
command n >>file | 将文件描述符n 以追加方式重定向到file 中 |
引入外部脚本
类似于c/c++
的include
操作,bash
也可以引入其他文件中的代码
格式:
. filename # 注意点和文件名之间有一个空格
或
source filename