Shell脚本学习笔记(二)

第二章 使用结构化命令

2.1 if-else语句

最基本的结构化命令就是if-then语句,其中then部分,可以使用多条命令。

if 		command
then 	command
fi

//或者使用下面格式
if command; then
	command
fi

其他编程语言中,if语句之后的对象是一个等式,这个等式的求值结果是TRUE或者FALSE,但是bash shell的if会运行if后面的命令,如果该命令的退出状态码是0(命令运行成功),位于then部分的命令就会被执行如果该命令的退出码是其他值,then部分的命令就不会执行,bash shell会继续执行脚本中的下一个命令。fi语句用来标识if-then语句到此结束。

#此脚本在if行采用了pwd命令,如果命令成功结束,echo语句就会显示该文本字符串。
$ cat test1.sh
#!/bin/bash
# testing the if statement
if pwd
then
echo "It worked"
fi

由于IanNotaCommand是个错误的命令,所以会产生一个非零的退出的状态码,且bash shell会跳过then语句的echo语句。

$ cat test2.sh
#!/bin/bash
# testing a bad command
if IamNotaCommand
then
echo "It worked"
fi
echo "We are outside the if statement"
$
$ ./test2.sh
./test2.sh: line 3: IamNotaCommand: command not found
We are outside the if statement
2.2 if-then-eles语句

if语句中的命令返回退出状态码0时,then部分中的命令会被执行。当if语句中的命令返回非零退出状态码时,bash shell会执行else部分中的命令。

if		command
then	command
else	command
fi
2.3 嵌套if

可以使用else部分的另一种形式:elif。就不用写多个if-then语句。elif使用另一个if-then语句延续else部分。

$ cat test5.sh
#!/bin/bash
# Testing nested ifs
#
testuser=NoSuchUser
#
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
else
echo "The user $testuser does not exist on this system."
if ls -d /home/$testuser/
then
echo "However, $testuser has a directory."
fi
fi
$
$ ./test5.sh
The user NoSuchUser does not exist on this system.
/home/NoSuchUser/
However, NoSuchUser has a directory.

if-then-elif语句语法:

if 		command1
	then 	commands
elif	command2
	then	more commands
fi

在elif语句中,紧跟其后的else语句属于elif代码块,他并不属于之前的if-then代码块。

可以继续将多个elif语句串起来,形成一个大的if-then-elif嵌套组合。

if command1
	then	command set 1
elif command2
	then	command set 2
elif command3
	then	command set 3
elif command4
	then	command set 4
fi
2.4 test命令

test命令提供了测试命令退出状态码的功能。如果test命令中列出的条件成立,test命令就会退出并返回退出状态码0。

test condition

conditontest命令要测试的一系列参数和值。当使在if-then语句中使用test命令时,命令格式如下:

if test condition
then	commands
fi

如果不写test命令的condition部分,它会以非零的状态退出,并执行else语句块

#test测试为真执行then后语句
$ cat test6.sh
#!/bin/bash
# Testing the test command
#
my_variable="Full"
#
if test $my_variable
then
echo "The $my_variable expression returns a True"
#
else
echo "The $my_variable expression returns a False"
fi
$
$ ./test6.sh
The Full expression returns a True

#test测试为假,执行else后语句
$ cat test6.sh
#!/bin/bash
# Testing the test command
#
my_variable=""
#
if test $my_variable
then
echo "The $my_variable expression returns a True"
#
else
echo "The $my_variable expression returns a False"
fi
$
$ ./test6.sh
The expression returns a False

bash shell提供了另一种条件测试方法(使用方括号),无需在if-then语句中声明test命令。

if [ condition ]
then commands
fi

方括号定义了测试条件。第一个方括号之后和第二个方括号之前必须加上一个空格,否则就会报错。test命令可以判断三类条件:数值比较,字符串比较,文件比较。

2.4.1 数值比较

使用test命令最常见的情形是对两个数值进行比较数值比较符如下表:

比较描述
n1 -eq n2检查n1是否与n2相等
n1 -ge n2检查n1是否大于或等于n2
n1 -gt n2检查n1是否大于n2
n1 -le n2检查n1是否小于或等于n2
n1 -lt n2检查n1是否小于n2
n1 -ne n2检查n1是否不等于n2
$ cat numeric_test.sh
#!/bin/bash
# Using numeric test evaluations
#
value1=10
value2=11
#测试value1是否大于5
if [ $value1 -gt 5 ]
then
echo "The test value $value1 is greater than 5"
fi
#测试value1是否与value2相等
if [ $value1 -eq $value2 ]
then
echo "The values are equal"
else
echo "The values are different"
fi

bash shell只能处理整数,基于浮点数的函数不能正确处理。

2.4.2 字符串比较

条件测试还允许比较字符串值,比较符号如下表:

比较描述
str1 = str2检查str1是否和str2相同
str1 != str2检查str1是否和str2不同
str1 < str2检查str1是否比str2小
str1 > str2检查str1是否比str2大
-n str1检查str1的长度是否非0
-z str1检查str1的长度是否为0

字符串顺序:当时用字符串大于小于号时需进行转义,否则sehell会把字符串当做重定向符号。大于和小于顺序的判断和sort命令所采用的逻辑不同。

#未对>号进行转义,执行结果错误
$ cat badtest.sh
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 > $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi
$
$ ./badtest.sh
baseball is greater than hockey
$ ls -l hockey
-rw-r--r-- 1 rich rich 0 Sep 30 19:08 hockey

#对大于号进行转义
$ cat test9.sh
#!/bin/bash
# mis-using string comparisons
#
val1=baseball
val2=hockey
#
if [ $val1 \> $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi
$
$ ./test9.sh
baseball is less than hockey

第一个脚本把大于号解释成了输出重定向。因此,它创建了一个名为hockey的文件。

在比较测试中,大写字母被认为是小于小写字母的,但是**sort命令恰好相反**。比较测试中使用的是标准的ASCII顺序,根据每个字符的ASCII数值来决定排序结果。

2.4.3 字符串大小

-n-z可以检查一个变量是否含有数据

$ cat test10.sh
#!/bin/bash
# testing string length
val1=testing
val2=''
#
if [ -n $val1 ]
then
echo "The string '$val1' is not empty"
else
echo "The string '$val1' is empty"
fi
#
if [ -z $val2 ]
then
echo "The string '$val2' is empty"
else
echo "The string '$val2' is not empty"
fi
#
if [ -z $val3 ]
then
echo "The string '$val3' is empty"
else
echo "The string '$val3' is not empty"
fi
$
$ ./test10.sh
The string 'testing' is not empty
The string '' is empty
The string '' is empty

空的和未初始化的变量会shell脚本测试造成严重的影响。如果不是确定一个变量的内容,最好在将其用于数值或字符串比较之前先通过-n-z来测试一下是否含有数值。

2.5 文件比较

文件比较为shell编程中最为强大,也是用的最多的比较形式,文件标记可以测试Linux文件系统上文件和目录的状态。

比较描述
-d file检查file是否存在并是一个目录
-e file检查file是否存在
-f file检查file是否存在并是一个文件
-r file检查file是否存在并可读
-s file检查file是否存在并非空
-w file检查file是否存在并可写
-x file检查file是否存在并可执行
-O file检查file是否存在并属当前用户所有
-G file检查file是否存在并默认组与当前用户相同
file1 -nt file2检查file1是否比file2新
file1 -ot file2检查file1是否比file2旧

2.5.1 检查目录

-d会检查指定的目录是否存在系统中。如果需要将文件写入目录或者是准备切换到某个目录中,先进行-d检查是好习惯。

$ cat test11.sh
#!/bin/bash
# Look before you leap
#
jump_directory=/home/arthur
#
if [ -d $jump_directory ]
then
echo "The $jump_directory directory exists"
cd $jump_directory
ls
else
echo "The $jump_directory directory does not exist"
fi

2.5.2 检查对象是否存在

-e检查文件或目录是否存在。

$ cat test12.sh
#!/bin/bash
# Check if either a directory or file exists
#
location=$HOME
file_name="sentinel"

#检查用户是否具有$HOME目录
if [ -e $location ]
then #Directory does exist
echo "OK on the $location directory."
echo "Now checking on the file, $file_name."

#检查$HOME目录中是否存在sentinel文件
if [ -e $location/$file_name ]
then #File does exist
echo "OK on the filename"
echo "Updating Current Date..."
date >> $location/$file_name
#
else #File does not exist
echo "File does not exist"
echo "Nothing to update"
fi
#
else #Directory does not exist
echo "The $location directory does not exist."
echo "Nothing to update"
fi

2.5.3 检查文件

-f用于检查文件是否存在。

$ cat test13.sh
#!/bin/bash
# Check if either a directory or file exists
#
item_name=$HOME
echo "The item being checked: $item_name"
#
if [ -e $item_name ]
#Item does exist
then
echo "The item, $item_name, does exist."
echo "But is it a file?"
#
if [ -f $item_name ]
#Item is a file
then
echo "Yes, $item_name is a file."
#
else #Item is not a file
echo "No, $item_name is not a file."
fi
#
else #Item does not exist
echo "The item, $item_name, does not exist."
echo "Nothing to update"
fi

2.5.4 检查文件是否可读

使用-r进行文件可读检查,如果需要从文件中读取数据,最好先测试一下文件是否可读。

$ cat test14.sh
#!/bin/bash
# testing if you can read a file
pwfile=/etc/shadow
#
# first, test if the file exists, and is a file
if [ -f $pwfile ]
then
# now test if you can read it
if [ -r $pwfile ]
then
tail $pwfile
else
echo "Sorry, I am unable to read the $pwfile file"
fi
else
echo "Sorry, the file $file does not exist"
fi

2.5.5 检查空文件

使用-s检查文件是否为空,删除文件前使用-s检查文件是否为空可以避免删除空文件。当-s比较成功时,说明文件中有数据。

$ cat test15.sh
#!/bin/bash
# Testing if a file is empty
#
file_name=$HOME/sentinel
#
if [ -f $file_name ]
then
if [ -s $file_name ]
then
echo "The $file_name file exists and has data in it."
echo "Will not remove this file."
#
else
echo "The $file_name file exists, but is empty."
echo "Deleting empty file..."
rm $file_name
fi
else
echo "File, $file_name, does not exist."
fi

2.5.6 检查是否可写

-w判断你对文件是否有可写权限

if [ -w $item_name ]
then #Item is writable
echo "Writing current time to $item_name"
date +%H%M >> $item_name
#
else #Item is not writable
echo "Unable to write to $item_name"
fi

2.5.7 检查文件是否可执行

-x判断文件是否有可执行权限。如果要在shell脚本中运行大量脚本,-x发挥其作用。

$ cat test17.sh
#!/bin/bash
# testing file execution
#
if [ -x test16.sh ]
then
echo "You can run the script: "
./test16.sh
else
echo "Sorry, you are unable to execute the script"
fi

2.5.8 检查所属关系

-O检查你是否为文件的属主

$ cat test18.sh
#!/bin/bash
# check file ownership
#
if [ -O /etc/passwd ]
then
echo "You are the owner of the /etc/passwd file"
else
echo "Sorry, you are not the owner of the /etc/passwd file"
fi

2.5.9 检查默认属组关系

-G检查文件的默认组,如果文件的默认组和用户默认组相同,则测试成功-G只会检查默认组而非用户所属的所有组

$ cat test19.sh
#!/bin/bash
# check file group test
#
if [ -G $HOME/testing ]
then
echo "You are in the same group as the file"
else
echo "The file is not owned by your group"
fi

2.5.10 检查文件日期

-nt会判定一个文件是否比另一个文件新。如果文件比较新,那意味着该文件创建日期距离当下时间更近。-ot比较会判定一个文件是否比另一个文件旧,文件更旧意味着创建日期更早。

$ cat test20.sh
#!/bin/bash
# testing file dates
#
if [ test19.sh -nt test18.sh ]
then
echo "The test19 file is newer than test18"
else
echo "The test18 file is newer than test19"
fi
if [ test17.sh -ot test19.sh ]
then
echo "The test17 file is older than the test19 file"
fi

用于比较文件路径是相对于你运行该脚本的目录而言。-nt-ot选项都不会检查文件是否存在,所以在使用这两个选项前,先使用-f确定文件是否存在。

2.6 复合条件测试

if-then语句允许你使用布尔逻辑来组合测试,有两种布尔运算符可用:

[ condition1 ] && [ condition2 ]

[ condition1 ] || [ condition2]

第一种使用AND运算符来组合两个条件,即两个条件都满足是执行then部分命令。

第二种使用OR运算符来组合两个条件,当任一条件满足时执行then部分命令。

$ cat test22.sh
#!/bin/bash
# testing compound comparisons
#
if [ -d $HOME ] && [ -w $HOME/testing ]
then
echo "The file exists and you can write to it"
else
echo "I cannot write to the file"
fi
2.7 if-then高级特性

bash shell提供了两项可以在if-then语句中使用的高级特性:

  • 用于数学表达式的双括号
  • 用于高级字符串处理功能的双方括号

2.7.1 双括号

双括号命令可以在比较的过程中使用高级数学表达式。test命令只能在比较的过程中使用简单的算术操作。双括号提供了更多的数学符号。

#双括号语法
(( expression ))

expression可以是任意的数学赋值或比较表达式,常用数学表达式符号如下表:

符号描述
val++后增
val–后减
++val先增
–val先减
逻辑求反
~位求反
**幂运算
<<左位移
>>右位移
&位布尔和
|位布尔或
&&逻辑和
||逻辑或

可以在if语句中用双括号命令,也可以在脚本中的普通命令里来赋值。

$ cat test23.sh
#!/bin/bash
# using double parenthesis
#
val1=10
#
if (( $val1 ** 2 > 90 ))
then
(( val2 = $val1 ** 2 ))
echo "The square of $val1 is $val2"
fi

不需要对双括号中表达式里的大于号转义。这是双口号提供的另一个高级特性。

2.7.2 双方括号

提供了针对字符串比较的高级特性。

#语法如下
[ [expression] ]

双方括号里的expression使用了test命令中采用的标准字符串比较。同时也提供了test未提供的特性:模式匹配(pattern matching)。在模式匹配中,可以定义一个正则表达式来匹配字符串值。

$ cat test24.sh
#!/bin/bash
# using pattern matching
#
#能识别r开头的字符串
if [[ $USER == r* ]]
then
echo "Hello $USER"
else
echo "Sorry, I do not know you"
2.8 case命令

case命令可以替换判断较多的if-then-else语句。

$ cat test25.sh
#!/bin/bash
# looking for a possible value
#
if [ $USER = "rich" ]
then
echo "Welcome $USER"
echo "Please enjoy your visit"
elif [ $USER = "barbara" ]
then
echo "Welcome $USER"
echo "Please enjoy your visit"
elif [ $USER = "testing" ]
then
echo "Special testing account"
elif [ $USER = "jessica" ]
then
echo "Do not forget to logout when you're done"
else
echo "Sorry, you are not allowed here"
fi

case命令语法:

case variable in
pattern1 | pattern2) commands1;;
pattern3) 			 commands2;;
*)					 default commands;;
esac

case命令会将指定的变量与不同模式进行比较。如果变量和模式是匹配的,那么shell会执行为该模式指定的命令。

$ cat test26.sh
#!/bin/bash
# using the case command
#
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica)
echo "Do not forget to log off when you're done";;
*)
echo "Sorry, you are not allowed here";;
esac

本章小结

1.介绍了结构化语句(if语句相关)

2.介绍了test命令,方括号条件测试

3.介绍了文件比较命令

4.复合条件测试

5.if语句的高级特性

6.case命令

参考文献:Linux命令行与shell脚本编程大全(第三版)Richard Blum Christine Bresnahan著 门佳 武海峰译

1. 什么是shell脚本Shell脚本是一种编程语言,它是在Unix和Linux操作系统中使用的一种脚本语言。它可以帮助用户自动化任务,并且可以运行一系列命令。 Shell脚本通常以.sh扩展名结尾。 2. 为什么要学习shell脚本学习shell脚本可以帮助你自动化任务,提高工作效率。Shell脚本也可以帮助你编写小工具,方便你自己或其他人使用。Shell脚本还可以帮助你更好地理解Linux和Unix操作系统。 3. 如何编写一个简单的shell脚本? 首先,在命令行中输入命令nano test.sh,创建一个名为test.sh的文件。然后,在文件中输入以下内容: #!/bin/bash echo "Hello World" 接着,按下Ctrl + X,然后按下Y,最后按下Enter,保存并退出文件。接下来,您需要在命令行中输入以下命令: chmod +x test.sh ./test.sh 这将使test.sh文件可执行,并运行脚本。在命令行中,您应该看到输出“Hello World”。 4. shell脚本中的注释是什么? 注释是用于向脚本中添加说明和文档的文本。在Shell脚本中,注释以“#”开头。注释不会被脚本解释器执行,但可以帮助其他人更好地理解脚本。 5. 如何在shell脚本中使用变量? 变量是一个用于存储值的占位符。在Shell脚本中,您可以使用以下语法来定义变量: my_variable="Hello World" 您可以使用echo命令来输出变量的值: echo $my_variable 6. 如何在shell脚本中使用条件语句? 在Shell脚本中,您可以使用条件语句来执行基于条件的操作。以下是一个示例条件语句: if [ $my_variable = "Hello World" ] then echo "The variable contains Hello World" else echo "The variable does not contain Hello World" fi 7. 如何在shell脚本中使用循环? 在Shell脚本中,您可以使用for循环或while循环来执行重复的操作。以下是一个示例for循环: for i in 1 2 3 4 5 do echo $i done 以上代码将输出数字1到5。 8. 如何在shell脚本中使用函数? 在Shell脚本中,您可以使用函数来组织和重复使用代码。以下是一个示例函数: function say_hello { echo "Hello World" } 您可以通过以下方式调用函数: say_hello 9. 如何从shell脚本中读取用户输入? 在Shell脚本中,您可以使用read命令来从用户那里读取输入。以下是一个示例: echo "What is your name?" read name echo "Hello $name" 以上代码将提示用户输入他们的名字,并输出“Hello”后跟用户的名字。 10. 如何在shell脚本中使用命令行参数? 在Shell脚本中,您可以使用$1、$2、$3等变量来访问命令行参数。例如,以下是一个示例脚本,它接受两个命令行参数并将它们相加: #!/bin/bash sum=$(($1 + $2)) echo "The sum of $1 and $2 is $sum" 您可以使用以下命令来运行脚本并传递两个参数: ./test.sh 2 3 以上代码将输出“The sum of 2 and 3 is 5”。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

搬砖小张

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值