shell脚本基础

shell相关概念

shell和shell脚本

shell是一个用 C 语言编写的程序,它是用户使用Unix/Linux的桥梁,用户的大部分工作都是通过shell完成的。shell虽然不是Unix/Linux系统内核的一部分,但它调用了系统核心的大部分功能来执行程序、建立文件并以并行的方式协调各个程序的运行。

而shell脚本,是一种为shell编写的脚本程序。shell脚本是解释执行的,不需要编译。

本文中的各shell脚本示例均是在OSX系统编写和执行,其它系统可能会有一些较小的差别。

shell脚本解释器

shell脚本的执行需要解释器,最常见的有sh和bash:

  • sh

sh全称Bourne Shell,是UNIX最初使用的shell,在每种 UNIX 上都可以使用

  • bash

bash全称Bourne Again Shell,是Linux默认的shell脚本解释器,是Bourne Shell的扩展

在编写shell脚本时,需要在脚本的第一行指定执行脚本的解释器,

在脚本的第一行需要指定执行脚本的解释器,如指定为sh:

1
#!/bin/sh

或指定bash:

1
#!/bin/bash

除了以上两种之外,还有一些其它常见的shell脚本解释器,如C Shell(/usr/bin/csh)、K Shell(/usr/bin/ksh)和Shell for Root(/sbin/sh)等。

脚本的执行

对于shell脚本文件script.sh

1
2
3
4
# 首先为脚本增加执行权限
chmod +x script.sh
# 运行
./script.sh

注释

注释分为单行注释和多行注释。单行注释用#标记注释的开始:

1
# comment

多行注释可以通过很多种方式实现,比较常用的一种如下:

1
2
3
4
5
: '
comment 1
comment 2
comment 3
'

变量

定义与使用

定义变量时,直接使用“变量名=变量值”,注意变量名与等号、等号与变量值之间不能有空格,如:

1
variableName="value"

变量名首个字符必须为大写或小写字母;中间不能有空格,可以使用下划线(_);不能使用标点符号;不能使用保留的关键字。

使用已经定义过的变量时,在变量名之前加$符号即可(为了标记变量名的边界,需要使用大括号将变量名包起来):

1
2
3
4
5
6
variableName="value"
echo $variableName # 输出 "value"
echo ${variableName} # 输出 "value"
echo ${variableName}IsTheValueOfVariableName # 使用大括号标记变量名边界
variableName="value2" # 修改变量的值 注意此时不加$符号 相当于重新定义
echo $variableName # 输出 "value2"

设为只读

将变量设置为只读,设置为只读的变量不能对其重新赋值:

1
readonly variableName

销毁

当不再使用一个变量时,即可将其销毁:

1
unset variableName

注意unset不可作用于只读的变量。

操作环境变量

在shell脚本中可以查看或修改系统的环境变量,如:

1
2
3
echo $PATH
echo $HOME
echo $PWD

脚本执行参数

在执行shell脚本时,可以向脚本传递参数,跟在脚本名称后边,使用空格分隔,如:

1
./test.sh debug 1 666

表示执行脚本test.sh,同时向脚本传递三个参数,依次为debug1666。在脚本内部,可以通过$n的形式获取脚本执行参数,对于上述命令,在test.sh内部可获取到的$0$1$2$3依次为:./test.shdebug1666

除了使用$n获取执行参数之外,还有一些其它的特殊变量:

  • $#: 传递给脚本的执行参数的个数
  • $*: 以一个单字符串显示所有向脚本传递的参数。"$*"将以 "$1 $2 ... $n" 的形式输出所有参数
  • $@: 与$*相同,"$@"将以 "$1" "$2" ... "$n" 的形式输出所有参数
  • $$: 脚本运行的当前进程ID号
  • $!: 后台运行的最后一个进程的ID号
  • $-: 显示Shell使用的当前选项
  • $?: 显示最后命令的退出状态,0表示没有错误,其他任何值表明有错误

字符串

字符串的表示

字符串可以用双引号或者单引号表示,两种方法表示的字符串略有不同:

使用双引号

双引号表示的字符串中,可以使用变量或转义字符,

1
2
3
name="world"
str1="Hello ${name}! "
str2="name is \"$name\" "

使用单引号

使用单引号时,单引号内部的变量和转义字符不会生效,而是保留字面内容:

1
2
name='world'
str='$name is "world"'

字符串的操作

获取长度

使用#来获取字符串长度:

1
2
3
string="hello"
length=${#string}
echo $length

字符串拼接

其实是在字符串中包含字符串变量:

1
2
3
4
str1="hello"
str2="world"
str3="${str1} ${str2}!"
echo $str3

提取子串

提取字符串具体有以下四种方式:

  • str:B:指定起始位置,截取到最后
  • str:B:L:指定起止位置和截取长度
  • str:0-B:反向指定起始位置,截取到最后
  • str:0-B:L:反向指定起始位置,并指定向后截取的长度
1
2
3
4
5
str="hello world"
echo ${str:6} # 输出 world
echo ${str:2:2} # 输出 ll
echo ${str:0-5} # 输出 world
echo ${str:0-9:2} # 输出 ll

截取字符串

  • #: 从左开始算起,截取第一个匹配的字符
  • ##: 从左开始算起,截取最后一个匹配的字符
  • %: 从右开始算起,截取第一个匹配的字符
  • %%: 从右开始算起,截取最后一个匹配的字符

具体参看示例代码:

1
2
3
4
5
str="http://www.hello.com/world.html"
echo "${str#*/}" # /www.hello.com/world.html
echo "${str##*/}" # world.html
echo "${str%/*}" # http://www.hello.com
echo "${str%%/*}" # http:

数组

bash仅支持一维数组(不支持多维数组),不限定数组的大小。数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。

定义数组

可以直接声明多个值,也可以单独指定各个值:

1
2
3
4
5
6
array1=(value0 value1 value2)
array2[0]=value0
array2[1]=value1
array2[2]=value2
echo ${array1[*]} # value0 value1 value2
echo ${array2[*]} # value0 value1 value2

使用数组

获取数组中的某个元素,直接方括号加下标:

1
2
3
4
array=(value0 value1 value2)
echo "arrry[0] is ${array[0]}"
echo "arrry[1] is ${array[1]}"
echo "arrry[2] is ${array[2]}"

如需获取所有元素,可以使用[*][@],具体参考下例:

1
2
3
array=(value0 value1 value2)
echo "arrry is ${array[*]}"
echo "arrry is ${array[@]}"

获取数组长度的方法与字符串相似,使用#

1
2
3
array=(value0 value1 value2)
echo "length: ${#array[*]}"
echo "length: ${#array[@]}"

echo和printf

在shell中两个命令echoprintf,都用于向屏幕显示信息,首先是echo的用法:

echo

显示字符串

echo用来显示字符串,当字符串使用双引号表示时,可包含转义字符或变量,字符串两端的双引号可以省略。如果想保持字符串内容原封不动输出,则用单引号表示字符串。某些情况下转义字符不能正常显示,则需要在echo命令之后加上参数-e启用转义:

1
echo -e "abc\ndef\a"

以上命令会输出两行字符abcdef,并且发出警告声(\a)。

换行控制

默认每次执行echo会在输出内容最后换行,如果在echo命令之后跟随参数-n则可以强制不换行。也可以使用以下的转义字符控制是否换行或调整光标位置,注意以下转义字符可能需要使用-e参数来开启:

  • \b 删除前一个字符
  • \c 最后不加上换行符号
  • \f 换行但光标仍旧停留在原来的位置
  • \n 换行且光标移至行首
  • \r 光标移至行首,但不换行
  • \t 插入tab
  • \v\f相同

显示命令执行结果

1
2
echo `date`        # 显示当前日期
echo `expr 1 + 1` # 2

结果定向至文件

1
echo "hello" > file.txt

printf

shell中的printf命令与C语言中的相似,用于格式化输出,语法为:

1
printf  format-string  [arguments...]

如:

1
printf "hello %s\n" "world"   # hello world

注意与C语言中不同的几处:

  • printf命令不用加括号

  • format-string可以没有引号,但最好加上,单引号双引号均可

  • 参数多于格式控制符%时,format-string可以重用,可以将所有参数都转换,后边给出例子

  • 参数少于格式控制符%时,那么%s用空字符串(NULL)代替,%d0代替

  • arguments使用空格分隔,不用逗号

以下是几个例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
printf "=========== TEST 1 ===========\n"
printf "%d %s\n" 1 "hello"
printf "=========== TEST 2 ===========\n"
printf '%d %s\n' 1 "world"
printf "=========== TEST 3 ===========\n"
printf %s hahaha
printf "\n"
printf "=========== TEST 4 ===========\n"
printf "%s %s %s\n" a b c d e f g h i j
printf "=========== TEST 5 ===========\n"
printf "%s and %d \n"
printf "=========== TEST 6 ===========\n"
printf "%-10s %-8s %-4s\n" 姓名 性别 体重kg
printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234
printf "%-10s %-8s %-4.2f\n" 杨过 男 48.6543
printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876

以上命令输出为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
=========== TEST 1 ===========
1 hello
=========== TEST 2 ===========
1 world
=========== TEST 3 ===========
hahaha
=========== TEST 4 ===========
a b c
d e f
g h i
j
=========== TEST 5 ===========
and 0
=========== TEST 6 ===========
姓名 性别 体重kg
郭靖 男 66.12
杨过 男 48.65
郭芙 女 47.99

运算符

shell本身不支持运算操作,但是可以借助expr命令来实现:

使用expr命令

使用expr命令时,需要将整个语句用(`)括起来,以下是一个简单的例子:

1
echo `expr 1 + 1`

算术运算

在使用expr进行算术运算时,注意运算数与运算符之间必须要有一个空格,否则会语法错误。以下是一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a=25
b=10

val=`expr $a + $b`
echo "a + b : $val"

val=`expr $a - $b`
echo "a - b : $val"

val=`expr $a \* $b`
echo "a * b : $val"

val=`expr $a / $b`
echo "a / b : $val"

val=`expr $a % $b`
echo "a % b : $val"

以上执行结果为:

1
2
3
4
5
a + b : 35
a - b : 15
a * b : 250
a / b : 2
a % b : 5

使用let命令

let是用于计算的语句,可用于执行一个或多个表达式,变量计算中不需要加上$来表示变量。以下是一个示例:

1
2
3
let a=10+25
let b=10-25
echo $a $b

除此之外,还可以通过let来实现变量的自增和自减:

1
2
3
4
5
6
7
8
9
10
num=1
echo $num
let num++
echo $num
let num--
echo $num
let num+=2
echo $num
let num-=3
echo $num

关系比较

用于比较关系的表达式必须用方括号括起来,且注意运算数与运算符之间必须要有一个空格。

在shell中,用于比较的关系的运算符有符号型的和字母型的两类,字母型的比较运算符适用于数值的比较,参考以下示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
a=10
b=25
if [ $a -eq $b ]
then
echo "$a -eq $b : a is equal to b"
else
echo "$a -eq $b: a is not equal to b"
fi
if [ $a -ne $b ]
then
echo "$a -ne $b: a is not equal to b"
else
echo "$a -ne $b : a is equal to b"
fi
if [ $a -gt $b ]
then
echo "$a -gt $b: a is greater than b"
else
echo "$a -gt $b: a is not greater than b"
fi
if [ $a -lt $b ]
then
echo "$a -lt $b: a is less than b"
else
echo "$a -lt $b: a is not less than b"
fi
if [ $a -ge $b ]
then
echo "$a -ge $b: a is greater or equal to b"
else
echo "$a -ge $b: a is not greater or equal to b"
fi
if [ $a -le $b ]
then
echo "$a -le $b: a is less or equal to b"
else
echo "$a -le $b: a is not less or equal to b"
fi

符号型的运算符可用来比较数值,也可以用来比较字符串,以下是一些例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
a="A"
b="B"
if [ $a = $b ]
then
echo "a is equal to b"
fi
if [ $a == $b ]
then
echo "a is equal to b"
fi
if [ $a != $b ]
then
echo "a is not equal to b"
fi
if [ $a > $b ]
then
echo "a is greater than b"
fi
if [ $a < $b ]
then
echo "a is less than b"
fi

布尔运算

shell中,用!表示“非”, -a表示“与”, -o表示“或”:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
a=10
b=25

if [ $a != $b ]
then
echo "$a != $b : a 不等于 b"
else
echo "$a != $b: a 等于 b"
fi
if [ $a -lt 100 -a $b -gt 15 ]
then
echo "$a -lt 100 -a $b -gt 15 : 返回 true"
else
echo "$a -lt 100 -a $b -gt 15 : 返回 false"
fi
if [ $a -lt 100 -o $b -gt 100 ]
then
echo "$a -lt 100 -o $b -gt 100 : 返回 true"
else
echo "$a -lt 100 -o $b -gt 100 : 返回 false"
fi
if [ $a -lt 5 -o $b -gt 100 ]
then
echo "$a -lt 100 -o $b -gt 100 : 返回 true"
else
echo "$a -lt 100 -o $b -gt 100 : 返回 false"
fi

逻辑运算符

逻辑运算符与布尔运算符起着相似的作用,用 &&表示“与”, ||表示“或”:,但在表达形式上有不同,此时表达式应使用双层方括号:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
a=10
b=25

if [[ $a -lt 100 && $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi

if [[ $a -lt 100 || $b -gt 100 ]]
then
echo "返回 true"
else
echo "返回 false"
fi

字符串测试

在shell中,除了之前的相等、不相等之外,有一些其它的字符串测试运算符,具体如下:

  • -z:检测字符串长度是否为0,如果是0,返回true,否则返回false
  • -n:检测字符串长度是否为0,如果是0,返回false,否则返回true
  • [ ]:检测字符串是否为空,如果是空,返回false,否则返回true

以下是一些用法示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
str=''
if [ -z $str ]
then
echo "-z $str : 字符串长度为 0"
else
echo "-z $str : 字符串长度不为 0"
fi
if [ -n "$str" ]
then
echo "-n $str : 字符串长度不为 0"
else
echo "-n $str : 字符串长度为 0"
fi
if [ $str ]
then
echo "[ $str ] : 字符串不为空"
else
echo "[ $str ] : 字符串为空"
fi

流程控制

分支结构

if语句

之前的示例代码中已经用到了分支结构,现在具体讲述。条件分之语句主要结构如下,其中可以没有elseelif分支,也可以有多个并列的elif分支。需要注意的是,分支内的语句不能为空。在分支语句的最后必须有fi标记结束。

1
2
3
4
5
6
7
8
9
10
11
12
if [ expression1 ]
then
Statement(s) to be executed if expression1 is true
elif [ expression2 ]
then
Statement(s) to be executed if expression2 is true
elif [ expression3 ]
then
Statement(s) to be executed if expression3 is true
else
Statement(s) to be executed if no expression is true
fi

在条件语句中,表达式和方括号之间必须有空格,否则会有语法错误。

case语句

与C语言中的switch...case结构相似,但写法大不相同。shell中的case语句结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
case 值 in
模式1)
command1
command2
command3
;;
模式2)
command1
command2
command3
;;
*)
command1
command2
command3
;;
esac

以下是一个示例,输入一个数字,根据输入的数字进行判断执行分支语句:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo 'Input a number between 1 to 4'
echo 'Your number is:\c'
read aNum
case $aNum in
1) echo 'You select 1'
;;
2) echo 'You select 2'
;;
3) echo 'You select 3'
;;
4) echo 'You select 4'
;;
*) echo 'You do not select a number between 1 to 4'
;;
esac

如果多种模式对应同一种相同的处理方式,则可以将模式合并:

1
2
3
4
5
6
7
8
9
10
11
12
while :
do
echo -n "Input a number between 1 to 5: "
read aNum
case $aNum in
1|2|3|4|5) echo "Your number is $aNum!"
;;
*) echo "You do not select a number between 1 to 5, game is over!"
break
;;
esac
done

循环结构

for循环

for循环的结构如下所示,其中“列表”可以是一个数组,或者用空格分隔的数字或字符串:

1
2
3
4
5
6
7
for 变量 in 列表
do
command1
command2
...
commandN
done

以下是具体的示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
arr=(1 2 3)
for var in ${arr[*]}
do
echo "$var"
done
# 逐个输出数组中的元素
echo '==================='
for var in a bc def
do
echo "$var"
done
# 逐个输出列表字符串
echo '==================='
for var in $HOME/.bash*
do
echo $var
done
# 逐个输出$HOME目录下以.bash开头的文件

while循环

while循环结构如下:

1
2
3
4
while condition
do
command
done

非常简单,以下是一个示例:

1
2
3
4
5
6
int=1
while(( $int<=5 ))
do
echo $int
let "int++"
done

另一个例子:

1
2
3
4
5
6
int=1
while [[ $int -le 5 ]]
do
echo $int
int=`expr $int + 1`
done

while可用于构造无限循环,格式如下:

1
2
3
4
while :
do
command
done

1
2
3
4
while true
do
command
done

也可以使用while配合read来获取用户输入,以下是一个示例:

1
2
3
4
5
echo -n 'please type a number: '
while read num
do
echo "your number is $num"
done

until循环

until循环中,循环结构一直执行,直到条件为真时停止:

1
2
3
4
until condition
do
command
done

以下是一个示例:

1
2
3
4
5
6
a=9
until [ ! $a -lt 10 ]
do
echo $a
a=`expr $a + 1`
done

执行后会输出:

1
9

break和continue

使用break可以跳出循环,当有多层循环嵌套时,break可以跟一个参数用以指定跳出第几层循环,以下是两个break的使用案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break # inner loop
else
echo "$var1 $var2"
fi
done
done

echo '================================'

for var1 in 1 2 3
do
for var2 in 0 5
do
if [ $var1 -eq 2 -a $var2 -eq 0 ]
then
break 2 # outter loop
else
echo "$var1 $var2"
fi
done
done

以上脚本执行输出结果为:

1
2
3
4
5
6
7
1 0
1 5
3 0
3 5
================================
1 0
1 5

continue会跳过本次循环,并继续执行循环,与C语言中相似,不再赘述。

文件测试

以下是shell中文件测试运算符:

运算符 描述
-b file 检测文件是否是块设备文件,如果是,则返回 true
-c file 检测文件是否是字符设备文件,如果是,则返回 true
-d file 检测文件是否是目录,如果是,则返回 true
-f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true
-g file 检测文件是否设置了 SGID 位,如果是,则返回 true
-k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true
-p file 检测文件是否是具名管道,如果是,则返回 true
-u file 检测文件是否设置了 SUID 位,如果是,则返回 true
-r file 检测文件是否可读,如果是,则返回 true
-w file 检测文件是否可写,如果是,则返回 true
-x file 检测文件是否可执行,如果是,则返回 true
-s file 检测文件是否为空(文件大小是否大于0),不为空返回 true
-e file 检测文件(包括目录)是否存在,如果是,则返回 true

一个例子:

1
2
3
4
5
6
7
8
# touch ./test.sh
file="./test.sh"
if [ -e $file ]
then
echo "File exists"
else
echo "File does not exist"
fi

IO重定向

Unix 命令默认从标准输入设备(stdin)获取输入,将结果输出到标准输出设备(stdout)显示。一般情况下,标准输入设备就是键盘,标准输出设备就是终端,即显示器。

基本操作

使用IO重定向,可以从文件读取输入,或者将输出写到文件中。以下是一些重定向操作:

指令 描述
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之间的内容作为输入。

注意表中的文件描述符n,文件描述符0 通常是标准输入(stdin),1 是标准输出(stdout),2 是标准错误输出(stderr)。

以下是一些示例:

1
2
3
4
5
echo hello world > file1.txt # 向file1写入
echo hello world again >> file1.txt # 向file1追加
echo 3rd line >> file1.txt # 向file1追加
wc -l < file1.txt >> file1.txt # 获取file1的行数 并追加给file1
wc -l < file1.txt # 获取file1的行数并输出 应输出 4

此时file1.txt的内容如下:

1
2
3
4
hello world
hello world again
3rd line
3

Here Document

Here Document 是shell中的一种特殊的重定向方式,它的基本的形式如下,用于将两个delimiter之间的内容传递给command

1
2
3
command << delimiter
document
delimiter

如以下的示例代码,会输出3

1
2
3
4
5
6
wc -l << deli
hello world
hello world again
3rd line
deli
# 3

/dev/null 文件

如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到/dev/null/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。将命令的输出重定向到它,会起到”禁止输出”的效果。

例如,如果希望屏蔽 stdout(1)和 stderr(2),可以这样写:

1
command > /dev/null 2>&1

函数

shell中的函数需要先定义后使用,定义函数的方法如下,位于开始位置的function关键词也可以省略不写:

1
2
3
4
function function_name () {
list of commands
[ return value ]
}

函数的返回值可以使用return显式指定,也可以略去直接使用最后一行命令执行的结果作为返回值。函数的返回值只能是整数。调用函数时,直接使用函数名即可,不需要加括号。如果向函数传递参数,直接在函数后边跟上用空格分隔的参数列表,函数内部使用$n的方式获取,类似于脚本执行参数。在调用函数之后,获取函数的返回值应当使用#?

以下是两段示例代码:

1
2
3
4
5
fun1(){
echo "this is fun1"
}
fun1
echo "fun1 returns $?"

执行上边的脚本会得到以下输出:

1
2
this is fun1
fun1 returns 0

再来另一个示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
fun2(){
if [[ $1 -gt $2 ]]
then
echo "1st arg $1 is greater than 2nd arg $2"
elif [[ $1 -lt $2 ]]
then
echo "1st arg $1 is less than 2nd arg $2"
else
echo "1st arg $1 is equal to 2nd arg $2"
fi

return `expr $1 + $2`

}
fun2 10 25
echo "sum of two args is $?"

以上脚本执行结果如下:

1
2
1st arg 10 is less than 2nd arg 25
sum of two args is 35

文件包含

和其他语言一样,shell也可以包含外部脚本。这样可以很方便的封装一些公用的代码作为一个独立的文件。包含文件格式如下:

1
2
3
4
5
# 第一种形式 注意点号(.)和文件名中间有一空格
. filename

# 或者第二种形式
source filename

以下是一个简单示例:

首先准备文件file1.sh,里边输入内容如下,此时file1.sh不需要可执行权限:

1
2
3
4
5
#!/bin/bash
var1="var1 from file1"
func1(){
echo "func1 from file1"
}

接下来在新的脚本中输入以下内容:

1
2
3
. ./file1.sh
echo $var1
func1

执行之后会有以下输出结果:

1
2
var1 from file1
func1 from file1

REFERENCE

Shell脚本学习指南

http://www.runoob.com/linux/linux-shell.html

http://c.biancheng.net/cpp/view/6994.html