Shell 控制流程
if else
if
# 语法
if condition
then
command_1
command_2
...
fi
# 可写成
if condition ; then command1; command2; fi
if else
# 语法
if condition
then
command_1
command_2
...
else
command_N
...
fi
if else-if else
# 语法
if condition1
then
command_1
...
elif condition2
then
command_M
...
else
command_N
...
fi
if else 语句经常与test
命令搭配使用
有实例如下:
#!/bin/bash
if test $1 -eq $2
then
echo "两个数相等"
else
echo "两个数不相等"
fi
运行结果如下:
[root@aliyun test]# ./test.sh 100 200
两个数不相等
[root@aliyun test]# ./test.sh 100 100
两个数相等
for 循环
# 格式
for var in item1 item2 ... itemN
do
command_1
command_2
...
command_N
done
# 可写为
for var in item1 item2 ... itemN; do command_1; command_2; … done;
当变量值在列表中时,for循环即执行一次所有命令,使用变量名获取列表中的当前取值。命令可以为任何有效的shell命令和语句。in 列表可以包含替换、字符串和文件名
in 列表是可选的,如果不用它,for循环使用命令行的位置参数
有实例如下:
#!/bin/bash
for i in 1 2 3 4 5
do
echo -e "$i \c"
done
echo
for((i=1;i<=5;i++))
do
echo -e "$i \c"
done
echo
运行结果如下:
[root@aliyun test]# ./test.sh
1 2 3 4 5
1 2 3 4 5
有上述实例中可以看出,在shell中除了标准的for循环格式外,还支持类似C语言的for循环格式
while 语句
while condition
do
command
done
使用方法同理,此处不再赘述
无限循环
while :
do
command
done
# 或者
while true
do
command
done
# 或者
for (( ; ; ))
until 循环
until循环执行一系列命令直至调节键为 true才停止,其在处理方式上与while 循环相反,类似于C语言中的do…while() 语句
# 语法
until condition
do
command
done
condition 一般为条件表达式,如果返回值为false,则继续执行循环体内的语句,否则跳出循环
case
case语句为多分支选择结构语句。用 case 语句匹配一个值与一个模式,如果 匹配成功,执行相匹配的命令
其基本语法如下:
case 值 in
模式1)
command1
command2
...
commandN
;;
模式2)
command1
command2
...
commandN
;;
esac
模式取值可以为变量或者常数。匹配发现取值符合某一模式后,其间所有命令都会执行直到";;"停止
取值将检测匹配uude每一个模式。一旦模式匹配,则执行完 匹配模式相应命令后不再继续其他模式
如果没有检测到所有匹配的模式,就会使用星号(*)捕获,并执行其后命令
有实例如下:
#!/bin/bash
echo '输入 1 到 4 之间的数字:'
echo '你输入的数字为:'
read aNum
case $aNum in
1) echo '1'
;;
2) echo '2'
;;
3) echo '3'
;;
4) echo '4'
;;
*) echo '请输入 1 到 4 之间的数字'
;;
esac
运行结果如下:
[root@aliyun test]# ./test.sh
输入 1 到 4 之间的数字:
你输入的数字为:
3 # 标准输入
3 # 输出
break
break命令允许在未达到循环结束条件时强制跳出所有循环,终止执行后面的所有循环
continue
continue 命令类似 break 命令,都是在未达到循环结束条件时强制跳出循环的。不过,不同的是,continue 并不是跳出所有循环,而仅仅只是跳出当前循环
Shell 函数
Linux shell 支持用于定义函数,然后在 shell 脚本中可以随便调用。其格式如下:
[ function ] funname [()]
{
action;
...
[return int;]
}
说明:
- 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数
- 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果作为返回值
- return 后跟数值 ( 0 ~ 255 )
有如下实例:
#!/bin/bash
function Func(){
printf "请输入两个数字:\a"
read a_num b_num
echo -e "$a_num + $b_num = \c"
return $(($a_num+$b_num))
}
Func
echo "$?"
运行结果如下:
[root@aliyun test]# ./test.sh
请输入两个数字:10 20
10 + 20 = 30
[root@aliyun test]# ./test.sh
请输入两个数字:100 200
100 + 200 = 44
在上述实例中,细心地朋友可能会发现,第二次的运行结果并不正确
此处需要注意:
- shell中通过 return 返回是有限制的,最大返回255,超过255,则从0开始计算
$?
仅对其上一条指令负责,一旦函数返回后其返回值没有立即保存,那么不能使用 $? 来获取,会找不到这个返回值
函数参数
在shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n
的形式来获取参数的值。这个用法类似于脚本参数的传递方式,同样使用这个形式以获取值
将上述实例进行修改:
#!/bin/bash
function Func(){
echo -e "$1 + $2 = \c"
return $(($1+$2))
}
Func 10 20
echo "$?"
运行结果如下:
[root@aliyun test]# ./test.sh
10 + 20 = 30
【注意】:$10 不能用来获取第10个参数,需要使用${10} 。当 n >= 10 时,需要使用 ${n}
来获取参数
此外,还有以下几个特殊字符用来处理参数:
参数处理 | 说明 |
---|---|
$# | 传递到脚本的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程ID号 |
$! | 后台运行的最后一个进程的ID号 |
$@ | 与$*相同,但是使用时加引号,并在引号中返回每个参数 |
$- | 显示Shell使用的当前选项 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误 |
Shell 输入 / 输出 重定向
默认情况下,Linux 系统命令大多是从标准输入读取,并将输出结果写入标准输出,而一般标准输入和标准输出就是终端。简单来讲,改变一条指令的输入 或 输出位置就是重定向
重定向命令列表如下:
命令 | 说明 |
---|---|
command > file | 将输出重定向到 file |
command < file | 将输入重定向到 file |
command >> file | 将输出以追加的方式重定向到 file |
n > file | 将文件描述符为 n 的文件重定向到 file |
n >> file | 将文件描述符为 n 的文件以追加的方式重定向到 file |
n >& m | 将输出文件 m 和 n 合并 |
n <& m | 将输入文件 m 和 n 合并 |
<< tag | 将开始标记 tag 和结束标记 tag 之间的内容作为输入 |
一般情况下,每个UNIX / Linux 进程都会打开三个文件,即在命令运行时始终会存在着三个文件:
- 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数
- 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据
- 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息
默认情况下,command > file 将 stdout 重定向到 file,command < file 将stdin 重定向到file
如果希望将 stderr 重定向到 file:command 2 > file
如果希望将stderr 追加到file文件末尾:command 2 >> file
如果希望将 stdout 和 stderr 合并后重定向到 file:command > file 2>&1
如果希望对 stdin 和 stdout 都重定向:command < file1 > file2
Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式Shell脚本或程序
# 基本格式
command << delimiter
document
delimiter
作用:将两个 delimiter 之间的内容作为输入传递给 command
【注意】:
- 对格式要求严格:结尾的 delimiter 需要顶格写,前面和后面都不能有任何字符,包括空格和 tab 缩进
- 开始的 delimiter 前后的空格会被忽略掉
比如在终端中输入 cat << EOF
,系统会提示继续进行输入,输入多行信息后再次输入EOF,中间输入的信息将会显示在屏幕上
有实例如下:
[root@aliyun test]# cat << EOF
> First Line
> Second Line
> Third Line EOF
> EOF
First Line
Second Line
Third Line EOF
说明:
>
这个符号是终端产生的提示输入信息的标识符- EOF 只是一个标识而已,可以替换成任意的合法字符
又有实例 如:
#!/bin/bash
# ./test.sh 为当前文件
user_name="Adan-Xi"
cat << EOF > output1.sh
echo "Hello!"
echo $user_name # 此处的变量将被展开
EOF
cat << "FOE" > output2.sh
echo "Hello "
echo $user_name # 此处的变量将不会被展开
FOE
其输出如下:
[root@aliyun test]# ls
test.sh
[root@aliyun test]# ./test.sh
[root@aliyun test]# chmod +x output1.sh output2.sh
[root@aliyun test]# ls
output1.sh output2.sh test.sh
[root@aliyun test]# cat output1.sh
echo "Hello!"
echo Adam-Xi
[root@aliyun test]# cat output2.sh
echo "Hello "
echo $user_name
[root@aliyun test]# ./output1.sh
Hello!
Adam-Xi
[root@aliyun test]# ./output2.sh
Hello
# 此行输出为空
此处想借此例子说明,在这个重定向方式中,如果不想将 document 中的脚本变量展开,那么只需给delimiter加引号""
即可
/dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么就可以将输出重定向到 /dev/null:command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。
/dev/null 的作用是起到 禁止输出 的效果
Shell 文件包含
和其他语言一样,Shell 也可以包含外部文本,这样可以很方便的封装一些共用的代码作为一个独立的文件
其基本语法如下:
. filename # 注意此处(.)和文件名间有一个空格
# 或者
source filename
实例如下:
#!/bin/bash
# common.sh
user_name="Adam-Xi"
user_id=2344
echo "I am common.sh"
#!/bin/bash
# test1.sh
source ./common.sh
echo $user_name
#!/bin/bash
# test1.sh
. ./common.sh
echo $user_id
其输出结果如下:
[root@aliyun test]# chmod +x test1.sh test2.sh
[root@aliyun test]# ll
[root@aliyun test]# ll
total 20
-rw-r--r-- 1 root root 68 Mar 25 12:53 common.sh
-rwxr-xr-x 1 root root 49 Mar 25 12:55 test1.sh
-rwxr-xr-x 1 root root 42 Mar 25 12:56 test2.sh
-rwxr-xr-x 1 root root 4637 Mar 25 12:52 test.sh
[root@aliyun test]# ./test1.sh
I am common.sh
Adam-Xi
[root@aliyun test]# ./test2.sh
I am common.sh
2344
【注意】:
- 被包含的文件不一定需要可执行权限
- 执行顺序是:先执行被包含文件中的内容,在执行包含文件中的内容