shell脚本语法

条件测试

命令test 和 [ 可以测试一个条件是否成立,测试结果为真,该命令的exit status 为0, 测试结果为假,该命令的exit status 为1,
例如:测试两个数的大小关系
command:

itcast$ var=2			//初始化本地变量
itcast$ test $var -gt 1		//-gt(大于) greater的缩写,即 $var > 1
itcast$ echo $?			//exit status 为真 , 即 0

itcast$ test$var -gt 3		//-gt(大于) greater的缩写,即 $var > 3
itcast$ echo $?			//exit status 为假,  即 1

itcast$ [ $var -gt 3 ]		//-gt(大于) greater的缩写,即 $var > 3
itcast$ echo $?			//exit status 为假,  即 1

左中括号 “ [ “ 是一个命令, 传给命令的各个参数必须用空格隔开。
如上所述:[ $var -gt 3 ] 这条语句中, [ 括号命令拥有 $var, -gt, 3, ] , 4个参数。

常见的测试命令
command:

[ -d DIR ]			//如果DIR存在且为一个目录文件则为真,即exit status = 0
[ -f FILE ]			//如果FILE存在且为一个普通文件则为真,即exit status = 0
[ -z STRING ]			//如果STRING为空则为真, 即 exit status = 0
[ -n STRING ] 			//如果STRING非空则为真, 即 exit status = 0
[ STRING1 = STRING2 ]		//如果两个STRING相等则为真,即 exit status = 0
[ STRING1 != STRING2 ] 		//如果两个STRING不相等则为真, 即 exit status = 0

[ AGR1 OP AGR2 ]		//AGR1和AGR2应该是整数,或取值为整数的变量。

	//OP可以是以下选择
	
	//eq (等于)		即  equal 的缩写
	
	//ne (不等于)		即  unequel 的缩写

	//lt (小于)		即  less than 的缩写

	//le (小于等于)		即  less than or  equal to 的缩写
	
	//gt (大于)		即  greater than 的缩写

	//ge(大于等于)		即 greater than or  equal to  的缩写

测试条件还可以做逻辑或,与, 非 运算
command:

[ ! EXPR ] 			//EXPR可以是上述测试条件表达式中的任意一种, ! 表示逻辑非,取反
[ EXPR1 -a EXPR2 ]		//EXPR可以是上述测试条件表达式中的任意一种, -a   表示逻辑与
[ EXPR1 -o EXPR2 ]  		//EXPR可以是上述测试条件表达式中的任意一种, -o   表示逻辑或

使用逻辑测试
例如: 假设 001.sh 是普通文件, 003 是目录文件
command:

itcast$	[ -f '001.sh' -a -d '003' ]		//001.sh 是普通文件 且 003 是目录文件为真, 即 exit status = 0
itcast$	echo $?					//exit status = 0		
itcast$	[ -d '001.sh' -o -f '003' ]		//001.sh 是普通文件 或 003 是目录文件为真, 即 exit status = 0	
itcast$ echo $?					//eixt status = 1

分支

if/ then/ elif/ else/ fi

text:

if [ -f ~/.bashrc ]; then	# 当表达式中[ -f ~/.bashrc ] 为普通文件时,即 exit status = 0 时,执行 then 后续的代码
    . ~/.bashrc			# 执行语句
fi				#if 语句的结尾

其实是三条命令,if [ -f ∼/.bashrc ]是第一条,then . ∼/.bashrc是第二条,fi是第三条。如果两条命令写在同一行则需要用;号隔开,一行只写一条命令就不需要写;号了,另外,then后面有换行,但这条命令没写完,Shell会自动续行,把下一行接在then后面当作一条命令处理。
text:

#! /bin/sh

if [ -f /bin/bash ]		#当then 没有和表达式在一行时,表达式后面的;可以不写
then 
    echo "/bin/bash is a file"
else 				
    echo "/bin/bash is NOT a file"
fi

if :; then echo			# : 是一个特殊标记,即表达式总是为真
"always true"; fi		#当fi 和 执行语句在一行时,执行语句需要加上分号

text:

#! /bin/sh

echo "Is it morning?  Please answer yes or no."
read YES_OR_NO								#等待用户输入一行字符串,将该字符串存到变量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 0
fi
exit 0

shell 还提供 short circuiit ,提供 && 和 || 运算符。
text

test "$(whoami)" != 'root' && (echo you are using a non-privilegedaccount;exit 1)

&&相当于“if…then…”,而||相当于“if not…then…”。&&和||用于连接两个命令,而上面讲的-a和-o仅用于在测试表达式中连接两个测试条件,要注意它们的区别
例如:
text:

test "$VAR" -gt 1 -a "$VAR" -lt 3			
test "$VAR" -gt 1 && test "$VAR" -lt 3
#上述两个语句是等价的

case/esac
test:esac表示case语句块的结束,Shell脚本的case可以匹配字符串和Wildcard匹配整型或字符型常量表达式,每个匹配分支可以有若干条命令,末尾必须以;;结束。
text:

#! /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

循环

for/do/done
例如:
FRUIT是一个循环变量,第一次循环$FRUIT的取值是apple,第二次取值是banana,第三次取值是pear。
text:

#! /bin/sh

for FRUIT in apple banana pear; do
    echo "I like $FRUIT"
done

例如:将当前目录下的chap0、chap1、chap2等文件名改为chap0、chap1、chap2~等
text:

for FILENAME in chap?;do mv $FILENAME $FILENAME~; done		#不管文件存在不存在都执行 mv 操作。如果文件1不存在,将会产生错误。

for FILENAME in `ls chap?`; do mv $FILENAME $FILENAME~; done	#对存在的文件进行for循环,"`" 反引号括起来先执行命令代换,然后再执行 mv 操作

while/do/done
例如:创建无限循环
text:

#! /bin/sh
echo "Enter password:"
read TRY

while [ "$TRY" != "secret" ]; do
    echo "Sorry, try again"
    read TRY
done

text:
例如:创建有限循环

#! /bin/sh

COUNTER=1

while [ "$COUNTER" -lt 10 ]; do
    echo "Here we go again"
    COUNTER=$(($COUNTER+1))
done

until 循环
until 循环执行一系列命令直至条件为 true 时停止。 类似于 C语言中的 do while

until command
do
Statement(s) to be executed until command is true
done

text:

#!/bin/bash

a=0
until [ ! $a -lt 10 ]do
   echo $a
   a = $[ $a + 1 ]
done

break和continue
break[n]可以指定跳出几层循环;continue跳至本次循环起始位置,但不会跳出循环。
text

  1 #! /bin/sh
  2 
  3 echo "Enter password:"
  4 read TRY
  5 HHH1=1
  6 
  7 while [ "$TRY" != "secret" ]; do
  8     echo "Sorry, try again"
  9     if [ "$HHH1" -ge 3 ]; then
 10       break[1]
 11     fi
 12     HHH1=$["$HHH1" + 1]
 13     read TRY
 14     
 15 done
 16 

位置参数和特殊变量

有很多特殊变量是被Shell自动赋值的,例如

$0          相当于C语言main函数的argv[0]

$1$2...   这些称为位置参数(Positional Parameter),相当于C语言main函数的argv[1]、argv[2]...

$#          相当于C语言main函数的argc - 1,注意这里的#后面不表示注释

$@          表示参数列表"$1" "$2" ...,例如可以用在for循环中的in后面。

$*          表示参数列表"$1" "$2" ...,同上

$?          上一条命令的Exit Status

$$          当前进程号

位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,原来的$5现在变成$2等等,原来的$1、$2、$3丢弃,$0不移动。不带参数的shift命令相当于shift 1
command:

#! /bin/sh

echo "The program $0 is now running"
echo "The first parameter is $1"
echo "The second parameter is $2"
echo "The parameter list is $@ "
shift

echo "The first parameter is $1"
echo "The second parameter is $2"
echo "The parameter list is $@"

输入输出

echo
显示文本行或变量,或者把字符串输入到文件。
echo [option] string
command:

itcast$ echo"hello\n\n"		  
itcast$ echo -e "hello\n\n"	//-e 解析转义字符
itcast$ echo "hello"
itcast$ echo -n "hello"		//-n 不回车换行。默认情况echo回显的内容后面跟一个回车换行。

管道
可以通过 | 把一个命令的输出传递给另一个命令做输入。
command:

cat myfile | more	
ls -l | grep "myfile"
df -k | awk '{print $1}'| grep -v "文件系统"
//df -k 查看磁盘空间,找到第一列,去除“文件系统”,并输出

tee
tee命令把结果输出到标准输出,另一个副本输出到相应文件。
command:

df -k | awk '{print $1}' | grep -v "文件系统" | tee a.txt

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

文件重定向
command:

cmd > file              //把标准输出重定向到新文件中
cmd >> file             //追加
cmd > file 2>&1         //标准出错也重定向到1所指向的file里
cmd >> file 2>&1	//同上, 不同的是标准输入时属于追加的
cmd < file1 > file2 	//输入输出都定向到文件里,即cmd 从file1中读取数据,输入到flie2中
cmd < &fd               //把文件描述符fd作为标准输入
cmd > &fd               //把文件描述符fd作为标准输出
cmd < &-                //关闭标准输入

函数

Shell中也有函数的概念,但是函数定义中没有返回值也没有参数列表。
text:

#! /bin/sh 
foo(){ echo "Function foo is called";}
echo "-=start=-"
foo
echo "-=end=-"

函数体的左花括号 { 和后面的命令之间必须有空格或换行,如果将最后一条命令和右花括号 } 写在同一行,命令末尾必须有分号。

在定义foo()函数时并不执行函数体中的命令,就像定义变量一样,只是给foo这个名一个定义,到后面调用foo函数的时候(注意Shell中的函数调用不写括号)才执行函数体中的命令。Shell脚本中的函数必须先定义后调用,一般把函数定义语句写在脚本的前面,把函数调用和其它命令写在脚本的最后。

Shell函数没有参数列表并不表示不能传参数,事实上,函数就像是迷你脚本,调用函数时可以传任意个参数,在函数内同样是用$0、$1、$2等变量来提取参数,函数中的位置参数相当于函数的局部变量,改变这些变量并不会影响函数外面的$0、$1、$2等变量。函数中可以用return命令返回,如果return后面跟一个数字则表示函数的Exit Status。

这个脚本可以一次创建多个目录,各目录名通过命令行参数传入,脚本逐个测试各目录是否存在,如果目录不存在,首先打印信息然后试着创建该目录。
text:

#! /bin/sh

is_directory(){
    DIR_NAME=$1
    if [ ! -d $DIR_NAME ]; then
        return 1
    else
        return 0
    fi
}

for DIR in "$@"; do
    if is_directory "$DIR"; then :
    else
        echo "$DIR doesn't exist. Creating it now..."
        mkdir $DIR > /dev/null 2>&1
        if [ $? -ne 0 ]; then
            echo "Cannot create directory $DIR"
            exit 1
        fi
    fi
done

Shell脚本调试方法

1, -n 读一遍脚本中的命令但不执行,用于检查脚本中的语法错误。
command:

itcast$ sh -n 01.sh		//检查脚本的语法,不执行脚本的命令

2,-v 一边执行脚本,一边将执行过的脚本命令打印到标准错误输出。
command:

itcast$ sh -v 01.sh		//显示脚本所有行,详细模式,在脚本嵌套调用时比较有用

3,-x 提供跟踪执行信息,将执行的每一条命令和结果依次打印出来。
command:

itcast$ sh -x 01.sh		//在调用脚本的时候开启deubg

text:

#! /bin/sh -x			//在脚本开头提供参数。

在脚本中用set命令启用或禁用参数
text:

#! /bin/sh
if [ -z "$1" ]; then				//对脚本中的某一段进行跟踪调试

    set -x					//启用-x参数
    echo "ERROR: Insufficient Args."
    exit 1
    set +x					//禁用-x参数
    
fi
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值