shell脚本学习总结

1、执行脚本
文件头:#! /bin/sh
Shell 脚本中用 # 表示注释,相当于 C 语言的 // 注释。但如果 # 位于第一行开头,并且是 #! (称为 Shebang )则例外,它表示该脚本使用后面指定的解释器 /bin/sh 解释执行。如果把这个脚本文件加上可执行权限然后执行
执行方式:
(1)创建进程执行
itcast$chmod a+x test.sh
itcast$./test.sh

itcast$ /bin/sh ./test.sh
itcast$ (./test.sh)
shell会fork()出一个子进程来执行。

(2)在交互式shell下执行
itcast$ source ./test.sh
itcast$ . ./test.sh

2、基本语法
2.1、变量
Shell变量通常由字母加下划线开头,由任意 长度的字母、数字、下划 线组成。
(1)环境变量
环境变量可以从父进程传给子进程,因此 Shell 进程的环境变量可以从当前 Shell 进程传给 fork 出来的子进程。
(2)本地变量
环境变量是任何进程都有的概念,而本地变量是Shell 特有的概念。在Shell 中,环境变量和本地变量的定义和用法相似。在Shell 中定义或赋值一个 变量:
itcast$ VARNAME=value。 注意 等号两边都不能有空格 ,否则会被Shell 解释成命令和命令行参数。
一个变量定义后仅存在于当前Shell 进程,它是 本地变量 ,用export 命令可以把本地变量导出为环境变量,定义和导出环境变量通常可以一步完成:
eg1:用export命令把本地变量导出为环境变量。
itcast$ export VARNAME=value

eg2: unset 命令可以 删除 已定义的环境变量或本地变量。
itcast$ unset VARNAME

2.2、文件名代换( Globbing
通配符 Wildcard ),如:*? [] 具体如下:
    * 匹配0 个或多个任意字符
    ? 匹配一个任意字符
    [ 若干字符] 匹配方括号中任意一个字符的一次出现
 
itcast$ ls /dev/ttyS*
itcast$ ls ch0?.doc
itcast$ ls ch0[0-2].doc
itcast$ ls ch[012] [0-9].doc


2.3、命令代换( Globbing
(1)``
eg:
itcast$ DATE=`date`
itcast$ echo $DATE
(2)$()
eg:
itcast$ DATE=$(date)

2.4、算术代换
注意: +-*/ () 运算符,并且只能做整数运算

(1)$(()) 或者 $[]
eg
itcast$ VAR=45
itcast$ echo $(($VAR+3))    等价于   echo $[VAR+3]或 $[$VAR+3]

(2)$[base#n],其中 base表示进制,n按照 base 进行解释,后面再有运算数,
按十进制解释。
echo $[2#10+11]
echo $[8#10+11]
echo $[16#10+11]
2.5、变量替换
变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值

可以使用的变量替换形式:
形式 说明
${var} 变量本来的值
${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。
${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。
${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。
若此替换出现在Shell脚本中,那么脚本将停止运行。
${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。

2.6、转义字符
C 语言类似, \ Shell 中被用作转义字符,用于去除紧跟其后的单个字符的特殊意义(回车除外),换句话说,紧跟其后的字符取字面值。


2.7、单引号
C 语言同,Shell 脚本中的单引号和双引号一样都是字符串的界定符(双引号下一节介绍),而不是字符的界定符。单引号用于保持引号内所有字符的字面值,即使引号内的\ 和回车也不例外,但是字符串中不能出现单引号。如果引号没有配对就输入回车,Shell 会给出续行提示符,要求用户把引号配上对。例如:
itcast$ echo '$SHELL'
$SHELL
itcast$ echo 'ABC\ (回车)
> DE' (再按一次回车结束命令)
ABC\
DE

2.8、双引号

被双引号用括住的内容,将被视为单一字串。它防止通配符扩展,但允许变量扩展。这点与单引号的处理方式不同
itcast$ DATE=$(date)
itcast$ echo "$DATE"
itcast$ echo '$DATE'


3、shell脚本语法

3.1、条件测试

(1)命令 test [ 可以测试一个条件是否成立,如果测试结果为真, 则该命令的 Exit Status 0 ,如果测试结果为假, 则命令的 Exit Status 1 (注意与 C 语言的逻辑表示正好相反)。

eg、测试两个数的大小关系
itcast@ubuntu:~$ var=2
itcast@ubuntu:~$ test $var -gt 1
itcast@ubuntu:~$ echo $?
0
itcast@ubuntu:~$ test $var -gt 3
itcast@ubuntu:~$ echo $?
1
itcast@ubuntu:~$ [$var -gt 3]
itcast@ubuntu:~$ echo $?
1
(2)【】 传给命令的各参数之间应该用空格隔开,比如:[$VAR -gt 3 ] [ 命令的四个参数,它们之间必须用 空格隔开 。命令test [ 的参数形式是相同的,只不过test 命令不需要] 参数。以[ 命令为例, 常见的测试命令如下表所示:
[ -d DIR ] 如果DIR 存在并且是一个目录则为真
[ -f FILE ] 如果FILE 存在且是一个普通文件则为真
[ -z STRING ] 如果STRING 的长度为零则为真
[ -n STRING ] 如果STRING 的长度非零则为真
[ STRING1 = STRING2 ] 如果两个字符串相同则为真
[ STRING1 != STRING2 ] 如果字符串不相同则为真
[ ARG1 OP ARG2 ] ARG1 ARG2 应该是 整数或者取值为整数的变量
OP
-eq (等于)
-ne (不等于)
-lt (小于)
-le (小于等于)
-gt (大于)
-ge (大于等于)之中的一个。



C 语言类似,测试条件之间还可以做与、或、非逻辑运算:
[ EXPR1 -a EXPR2 ] EXPR1 EXPR2 可以是上表中的任意一种测试条件,-a 表示“逻辑与”
[ EXPR1 -o EXPR2 ] EXPR1 EXPR2 可以是上表中的任意一种测试条件,-o 表示“逻辑或”
eg:
$ VAR=abc
$ [ -d Desktop -a $VAR = 'abc' ]
$ echo $?
0

注意 ,如果上例中的$VAR 变量事先没有定义,则被Shell 展开为空字符串,会造成测试条件的语法错误(展开为[ -d Desktop -a = abc ] ), 作为一种好的 Shell 编程习惯 应该总是把变量取值放在双引号之中 (展开为[ -d Desktop -a “” = abc ] ):


3.2、分支
3.2.1、if/then/elif/else/fi

(1) : 是一个特殊的命令,称为空命令,该命令不做任何事,但 Exit Status 总是真。此外,也可以执行 /bin/true /bin/false 得到真或假的 Exit Status
eg:
#! /bin/sh
if [ -f /bin/bash ]
then
    echo "/bin/bash is a file"
else
    echo "/bin/bash is NOT a file"
fi
if :; then echo "always true"; fi

(2)read 命令 的作用是等待用户输入一行字符串,将该字符串存到一个 Shell 变量中。
eg:
#! /bin/sh
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
if [ "$YES_OR_NO" = "yes" ]; then
echo "Good morning!"
elif [ "$YES_OR_NO" = "no" ]; then
echo "Good afternoon!"
else
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
exit 1
fi
exit 0

3.2.2、case/esac
Shell 脚本的case 可以匹配字符串和Wildcard 每个匹配分支可以有若干条命令,末尾必须以 ;; 结束 ,执行时找到第一个匹配的分支并执行相应的命令,然后直接跳到esac 之后,不需要像C 语言一样用break 跳出。

eg:
#! /bin/sh
echo "Is it morning? Please answer yes or no."
read YES_OR_NO
case "$YES_OR_NO" in
yes|y|Yes|YES)
echo "Good Morning!";;
[nN]*)
     echo "Good Afternoon!";;
*)
echo "Sorry, $YES_OR_NO not recognized. Enter yes or no."
exit 1;;
esac
exit 0


3.3、循环
3.3.1、for/do/done

eg: 将当前目录下的 chap0 chap1 chap2 等文件名改为 chap0~ chap1~ chap2~

$ for FILENAME in chap?
do
mv $FILENAME $FILENAME~
done
也可以这样写:
$ for FILENAME in `ls chap?`
do
mv $FILENAME $FILENAME~
done

3.3.2、 while/do/done

eg1: 写一个验证密码的脚本
#! /bin/sh
echo "Enter password:"
read TRY
while [ "$TRY" != "secret" ]
do
echo "Sorry, try again"
read TRY
done

eg2: 循环10次
#! /bin/sh
  COUNTER=1
while [ "$COUNTER" -lt 10 ]
do
echo "Here we go again"
COUNTER=$(($COUNTER+1))
done

3.3.3、 break continue
(1)break[n] 可以指定跳出几层循环;
(2)continue 跳过本次循环,但不会跳出循环。
break 跳出,continue 跳过。

3.3.4、 until循环
until 循环格式为:
until commanddo Statement(s) to be executed until command is truedone
command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。

eg1 ,使用 until 命令输出 0 ~ 9 的数字:
  1. #!/bin/bash
  2. a=0
  3. until[!$a -lt10]
  4. do
  5. echo$a
  6. a=`expr$a+1`
  7. done


3.4、 位置参数和特殊变量
(1)$0 相当于C 语言main 函数的argv[0]
(2)$1 $2...   这些称为位置参数(Positional Parameter ),相当于C 语言main 函数的argv[1] argv[2]...
(3)$# 相当于C 语言main 函数的argc - 1 ,注意这里的# 后面不表示注释
(4)$@ 表示参数列表"$1" "$2" ... ,例如可以用在for 循环中的in 后面。
(5)$* 表示参数列表"$1" "$2" ... ,同上
(6)$? 上一条命令的Exit Status
(7)$$ 当前进程号
$* 和 $@ 的区别
$* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。
但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

4、输入输出
4.1、echo
echo [option] string
-e 解析转义字符
-n 不回车换行。默认情况echo 回显的内容后面跟一个回车换行。
eg
echo "hello\n\n"
echo -e "hello\n\n"
echo "hello"
echo -n "hello"

4.2、管道
可以通过 | 把一个命令的输出传递给另一个命令做输入。
eg:
cat myfile | more
ls -l | grep "myfile"
df -k | awk '{print $1}' | grep -v " 文件系统"
df -k 查看磁盘空间,找到第一列,去除“文件系统”,并输出
4.3、tee
tee 命令把结果输出到标准输出,另一个副本输出到相应文件。
eg1:
df -k | awk '{print $1}' | grep -v " 文件系统" | tee a.txt

tee -a a.txt 表示追加操作。
eg2:
df -k | awk '{print $1}' | grep -v " 文件系统" | tee -a a.txt


4.4、文件重定向
cmd > file              把标准输出重定向到新文件中
cmd >> file             追加
cmd > file 2>&1         标准出错也重定向到1 所指向的file
cmd >> file 2>&1
cmd < file1 > file2     输入输出都定向到文件里
cmd <&fd                把文件描述符fd 作为标准输入
cmd >&fd                把文件描述符fd 作为标准输出
cmd <&-                 关闭标准输入


命令 说明
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 之间的内容作为输入。
5、函数
原形
foo()
{
参数: $0 $1 ...
return ExitStatus
}

eg1: 带有return语句的函数:
  1. #!/bin/bash
  2. funWithReturn(){
  3. echo"The function is to get the sum of two numbers..."
  4. echo -n"Input first number: "
  5. read aNum
  6. echo -n"Input another number: "
  7. read anotherNum
  8. echo"The two numbers are $aNum and $anotherNum !"
  9. return$(($aNum+$anotherNum))
  10. }
  11. funWithReturn
  12. # Capture value returnd by last command
  13. ret=$?
  14. echo"The sum of two numbers is $ret !"
运行结果:
The function is to get the sum of two numbers...Input first number: 25Input another number: 50The two numbers are 25 and 50 !The sum of two numbers is 75 !
函数返回值在调用该函数后通过 $? 来获得。


eg2: 函数嵌套
  1. #!/bin/bash
  2. # Calling one function from another
  3. number_one () {
  4. echo"Url_1 is http://see.xidian.edu.cn/cpp/shell/"
  5. number_two
  6. }
  7. number_two () {
  8. echo"Url_2 is http://see.xidian.edu.cn/cpp/u/xitong/"
  9. }
  10. number_one
运行结果:
Url_1 is http://see.xidian.edu.cn/cpp/shell/Url_2 is http://see.xidian.edu.cn/cpp/u/xitong/


像删除变量一样,删除函数也可以使用 unset 命令,不过要加上 .f 选项,如下所示:
$unset . f function_name




6、Shell文件包含
Shell 中包含脚本可以使用:
  1. . filename
  1. source filename
两种方式的效果相同,简单起见,一般使用点号(.),但是注意点号(.)和文件名中间有一空格。

例如,创建两个脚本,一个是被调用脚本 subscript.sh,内容如下:
  1. url="http://see.xidian.edu.cn/cpp/view/2738.html"
一个是主文件 main.sh,内容如下:
  1. #!/bin/bash
  2. ../subscript.sh
  3. echo$url
执行脚本:
$chomd +x main.sh./main.shhttp://see.xidian.edu.cn/cpp/view/2738.html$
注意:被包含脚本不需要有执行权限。






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值