Linux基础知识(7)- Shell (五) | 函数、输入/输出重定向、文件包含
1. 函数
Linux shell 可以用户定义函数,在 shell 脚本中可以被调用。
1) 函数定义
shell 中函数的定义格式如下:
[ function ] fun [()]
{
action;
[return int;]
}
说明:
(1) 可以带 function fun() 定义,也可以直接 fun() 定义,不带任何参数。
(2) 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。 return 后跟数值 n (0-255)。
示例
1 #!/bin/bash 2 3 func() { 4 echo "第一个函数" 5 } 6 7 funWithReturn(){ 8 echo "第二个函数:输入的两个数字进行相加运算 ..." 9 echo "输入第1个数字: " 10 read num1 11 echo "输入第2个数字: " 12 read num2 13 echo "2个数字: $num1, $num2" 14 return $(($num1+$num2)) # 和 $[$num1+$num2] 同样效果,完成算术运算 15 } 16 17 echo "---- 函数开始执行 ----" 18 19 func # 不带 () 20 funWithReturn 21 22 echo "第二个函数返回值:$?" 23 24 echo "---- 函数执行结束 ----"
输出结果:
1 ---- 函数开始执行 ---- 2 第一个函数 3 第二个函数:输入的两个数字进行相加运算 ... 4 输入第1个数字: 5 3 6 输入第2个数字: 7 5 8 2个数字: 3, 5 9 第二个函数返回值:8 10 ---- 函数执行结束 ----
注:
(1) 函数返回值在调用该函数后通过 $? 来获得。
(2) 所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至 shell 解释器首次发现它时,才可以使用。
2) 函数参数
在 Shell 中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1 表示第一个参数,$2 表示第二个参数 ...
另外,还有几个特殊字符用来处理参数:
参数 | 描述 |
$# | 传递到脚本或函数的参数个数 |
$* | 以一个单字符串显示所有向脚本传递的参数 |
$$ | 脚本运行的当前进程 ID 号 |
$! | 后台运行的最后一个进程的 ID 号 |
$@ | 与 $* 相同,但是使用时加引号,并在引号中返回每个参数。 |
$- | 显示 Shell 使用的当前选项,与 set 命令功能相同。 |
$? | 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。 |
示例
1 #!/bin/bash 2 3 funWithParam(){ 4 echo "第1个参数: $1" 5 echo "第9个参数: $9" 6 echo "第10个参数:${10}" 7 echo "第11个参数:${11}" 8 echo "参数总数\$#:$#" 9 echo "所有参数\$*:$*" 10 echo "所有参数\$@:$@" 11 echo "当前进程 ID 号\$$:$$" 12 } 13 14 funWithParam 1 2 3 4 5 6 7 8 9 10 abc
输出结果:
1 第1个参数: 1 2 第9个参数: 9 3 第10个参数:10 4 第11个参数:abc 5 参数总数$#:11 6 所有参数$*:1 2 3 4 5 6 7 8 9 10 abc 7 所有参数$@:1 2 3 4 5 6 7 8 9 10 abc 8 当前进程 ID 号$$:11025
注:当 n >= 10 时,需要使用 ${n} 来获取参数。
2. 输入/输出重定向
在 Unix/Linux 中,接受文本作为输入是通过 stdin (标准输入流)。从命令输出到 Shell 的文本是通过 stdout (标准输出流) 传递。命令的错误消息通过 stderr (标准错误流) 发送。
Unix/Linux 中的流被视为文件,与进程关联的每个文件都分配有一个唯一的编号以进行标识,称为文件描述符。 文件描述符: 0 是标准输入(stdin),1 是标准输出(stdout),2 是标准错误输出(stderr)。
输入/输出在没有重定向的情况下(默认情况),输出到终端,从终端接收输入。
重定向命令列表如下:
命令 | 描述 |
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 之间的内容作为输入。 |
1) 标准输出(stdout)重定向
重定向到 file,格式如下:
$ command > file
或
$ command 1> file
以追加方式重定向到 file,格式如下:
$ command >> file
或
$ command 1>> file
示例
$ echo "重定向到 file,不指定文件描述符" > data.txt
$ cat data.txt
重定向到 file,不指定文件描述符
$ echo "重定向到 file,指定文件描述符" 1> data.txt
$ cat data.txt
重定向到 file,指定文件描述符
$ echo "以追加方式重定向到 file,不指定文件描述符" >> data.txt
$ cat data.txt
重定向到 file,指定文件描述符
以追加方式重定向到 file,不指定文件描述符
$ echo "以追加方式重定向到 file,指定文件描述符" 1>> data.txt
$ cat data.txt
重定向到 file,指定文件描述符
以追加方式重定向到 file,不指定文件描述符
以追加方式重定向到 file,指定文件描述符
注: “1>” 和 “1>>” 里的文件描述符 “1” 和 “>” 之间不能有空格,如果有空格,“1” 会被作为字符串处理,而不是作为文件描述符来处理。
2) 标准输入(stdin)重定向
格式如下:
$ command < file
示例
1 $ wc -l data.txt # 统计 data.txt 文件的行数 2 3 3 data.txt # 文件里有 3 行,并显示文件名 4 5 $ wc -l < data.txt 6 7 3 # 不显示文件名
3) 标准输出和输入同时重定向
格式如下:
$ command < infile > outfile
示例
1 $ wc -l < data.txt > result.txt # 统计 data.txt 文件的行数,把统计结果写到 result.txt 2 $ cat result.txt 3 4 3
4) 标准错误输出(stderr)重定向
重定向到 file,格式如下:
$ command 2> file
以追加方式重定向到 file,格式如下:
$ command 2>> file
将 stderr 和 stdout 合并后重定向到 file,格式如下:
$ command > file 2>&1
将 stderr 和 stdout 合并后重定向到 file,格式如下:
$ command >> file 2>&1
示例
1 $ ls test.sh aaa.sh # test.sh 存在,aaa.sh 不存在 2 3 ls: aaa.sh: No such file or directory 4 test.sh 5 6 $ ls test.sh aaa.sh 2> error.txt 7 8 test.sh 9 10 $ cat error.txt 11 12 ls: aaa.sh: No such file or directory 13 14 $ ls bbb.sh 2>> error.txt # bbb.sh 不存在 15 $ cat error.txt 16 17 ls: aaa.sh: No such file or directory 18 ls: bbb.sh: No such file or directory 19 20 21 $ ls test.sh aaa.sh > result.txt 2>&1 22 $ cat result.txt 23 24 ls: aaa.sh: No such file or directory 25 test.sh 26 27 $ ls test.sh bbb.sh >> result.txt 2>&1 28 $ cat result.txt 29 30 ls: aaa.sh: No such file or directory 31 test.sh 32 ls: bbb.sh: No such file or directory 33 test.sh
注:
(1) “2>” 和 “2>>” 里的文件描述符 “2” 和 “>” 之间不能有空格,如果有空格,“2” 会被作为字符串处理,而不是作为文件描述符来处理。
(2) "2>&1" 是一个整体,中间不能有空格,“2” 和 “1” 的位置不能交换。
5) Here Document
Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序。
格式如下:
command << delimiter
document
delimiter
它的作用是将两个 delimiter 之间的内容 (document) 作为输入传递给 command。
注:结尾的 delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进。开始的 delimiter 前后的空格会被忽略掉。
在命令行中通过 wc -l 命令计算 Here Document 的行数:
1 $ wc -l << EOF # 按回车键,进入输入模式,输入 3 行 2 >Hello world 3 >Good 123 4 >www.test.com 5 >EOF # 输入 EOF,按回车键,退出输入模式 6 7 3 # 输出结果为 3 行
也可以将 Here Document 用在脚本中,例如:
1 #!/bin/bash 2 3 cat << EOF 4 Hello world 5 Good 123 6 www.test.com 7 EOF
执行以上脚本,输出结果:
Hello world
Good 123
www.test.com
6) /dev/null 文件
如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 /dev/null:
$ command > /dev/null
/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到 "禁止输出" 的效果。
如果希望屏蔽 stdout 和 stderr,可以这样写:
$ command > /dev/null 2>&1
注:"2>&1" 是一个整体,中间不能有空格,“2” 和 “1” 的位置不能交换。
3. 文件包含
Shell 也可以包含外部脚本,可以方便的封装一些公用的代码作为一个独立的文件。
Shell 文件包含的语法格式如下:
. filename # 注意点号(.)和文件名中间有一空格
或
source filename
创建两个 shell 脚本文件。
demo1.sh 代码如下:
#!/bin/bash
url="http://www.test.com"
demo2.sh 代码如下:
1 #!/bin/bash 2 3 # 使用 . 号来引用 demo1.sh 文件 4 . ./demo1.sh 5 6 # 或者使用以下包含文件代码 7 # source ./demo1.sh 8 9 echo "Website:$url"
接下来为 demo2.sh 添加可执行权限并执行:
$ chmod +x demo2.sh
$ ./demo2.sh
Website:http://www.test.com
注:被包含的文件 demo1.sh 不需要可执行权限。