Bash脚本部署与编程全解析
1. 命令行参数的使用
在shell脚本中,我们可以使用命令行参数。例如
test4.sh
脚本:
#!/bin/bash
# Testing command line arguments
echo $1 checked in $2 days ago
使用以下命令为脚本添加执行权限并运行:
$ chmod u+x test4.sh
$ ./test4.sh Barbara 4
Barbara checked in 4 days ago
$ ./test4.sh Jessica 5
Jessica checked in 5 days ago
在这个脚本中,
$1
变量保存人的名字,
$2
变量保存他们签到的天数。需要注意的是,如果位置变量不存在,shell不会产生错误消息,但可能得不到预期的结果。例如:
$ ./test4.sh rich
rich checked in days ago
因此,需要在程序代码中检查位置变量是否存在。
2. 退出状态
当shell脚本结束时,它会向启动它的父shell返回一个退出状态。这个退出状态告诉我们脚本是否成功完成。Linux提供了特殊的
$?
变量,它保存了最后执行命令的退出状态值。要检查命令的退出状态,必须在命令结束后立即查看
$?
变量。
$ who
rich :0 2019-02-20 23:16 (:0)
$ echo $?
0
按照惯例,成功完成的命令的退出状态为0。如果命令执行出错,则退出状态为正整数值。可以使用
exit
命令更改shell脚本的退出状态。例如:
$ /bin/bash
$ exit 120
exit
$ echo $?
120
在编写更复杂的脚本时,可以通过更改退出状态值来指示错误,这样通过检查退出状态就可以轻松调试脚本。
3. 编写脚本程序
3.1 命令替换
命令替换允许将命令的输出分配给shell脚本中的用户变量。有两种命令替换格式:
- 用反引号(
)将命令括起来
- 使用
$()`函数
以下是示例代码:
$ var1=`date`
$ echo $var1
Fri Feb 18 18:05:38 EST 2022
$ var2=$(who)
$ echo $var2
rich :0 2022-02-18 17:56 (:0)
由于反引号和单引号容易混淆,在Linux世界中,
$()
函数格式更受欢迎。
3.2 数学运算
在Bash shell脚本中进行数学运算,对于整数运算,可以使用特殊格式
$[]
:
result=$[ 25 * 5 ]
但这种格式只支持整数,不支持浮点值。如果需要进行浮点计算,可以使用
bc
命令行计算器程序。例如:
$ bc
bc 1.07.1
Copyright 1991-1994, 1997, 1998, 2000, 2004, 2006, 2008, 2012-2017 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type 'warranty'.
12 * 5.4
64.8
3.156 * (3 + 5)
25.248
quit
$
不过,
bc
计算器有一些限制,浮点运算由内置变量
scale
控制,必须设置该变量才能得到预期的小数位数。例如:
$ bc -q
3.44 / 5
0
scale=4
3.44 / 5
.6880
quit
$
要将
bc
计算嵌入脚本,需要使用命令替换:
$ var1=$(echo "scale=4; 3.44 / 5" | bc)
$ echo $var1
.6880
$
对于大型编程项目,建议使用支持更多高级数学函数和特性的Z shell。
3.3 逻辑语句
3.3.1 if语句
if
条件语句的基本格式如下:
if [ condition ]
then
commands
fi
如果指定的条件计算为
True
逻辑值,shell将运行
then
部分的命令;如果为
False
,则跳过这些命令。条件表达式通常是比较两个值,Bash shell编程中有多种内置测试,如下表所示:
| 测试 | 类型 | 描述 |
| ---- | ---- | ---- |
| 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 |
| str1 = str2 | 字符串 | 检查str1是否与str2相同 |
| str1 != str2 | 字符串 | 检查str1是否与str2不同 |
| str1 < str2 | 字符串 | 检查str1是否小于str2 |
| str1 > str2 | 字符串 | 检查str1是否大于str2 |
| -n str1 | 字符串 | 检查str1的长度是否大于零 |
| -z str1 | 字符串 | 检查str1的长度是否为零 |
| -d file | 文件 | 检查文件是否存在且为目录 |
| -e file | 文件 | 检查文件是否存在 |
| -f file | 文件 | 检查文件是否存在且为普通文件 |
| -r file | 文件 | 检查文件是否存在且可读 |
| -s file | 文件 | 检查文件是否存在且不为空 |
| -w file | 文件 | 检查文件是否存在且可写 |
| -x file | 文件 | 检查文件是否存在且可执行 |
| -O file | 文件 | 检查文件是否存在且由当前用户拥有 |
| -G file | 文件 | 检查文件是否存在且默认组与当前用户相同 |
| file1 -nt file2 | 文件 | 检查file1是否比file2新 |
| file1 -ot file2 | 文件 | 检查file1是否比file2旧 |
以下是
test5.sh
脚本的示例:
#!/bin/bash
# testing the if condition
if [ $1 -eq $2 ]
then
echo "Both values are equal!"
exit
fi
if [ $1 -gt $2 ]
then
echo "The first value is greater than the second"
exit
fi
if [ $1 -lt $2 ]
then
echo "The first value is less than the second"
exit
fi
运行脚本:
$ chmod u+x test5.sh
$ ./test5.sh 10 5
The first value is greater than the second
$
只有计算为
True
逻辑值的
if
语句中的命令会被shell脚本处理。
3.3.2 case语句
case
语句允许以列表形式检查单个变量的多个值:
case variable in
pattern1) commands1;;
pattern2 | pattern3) commands2;;
*) default commands;;
esac
case
语句将指定的变量与不同的模式进行比较,如果变量与模式匹配,shell将执行该模式指定的命令。可以在一行中列出多个模式,用竖线分隔。星号是不匹配任何列出模式的值的通配符。例如
test6.sh
脚本:
#!/bin/bash
# using the case statement
case $USER in
rich | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit";;
testing)
echo "Special testing account";;
jessica)
echo "Don't forget to log off when you're done";;
*)
echo "Sorry, you're not allowed here";;
esac
运行脚本:
$ chmod u+x test6.sh
$ ./test6.sh
Welcome, rich
Please enjoy your visit
$
case
语句为每个可能的变量值指定各种选项提供了更简洁的方式。
3.4 循环
3.4.1 for循环
for
语句遍历系列中的每个元素,格式如下:
for variable in series ; do
commands
done
以下是
test7.sh
脚本的示例,用于遍历主文件夹中的文件:
#!/bin/bash
# iterate through the files in the Home folder
for file in $(ls | sort) ; do
if [ -d $file ]
then
echo "$file is a directory"
fi
if [ -f $file ]
then
echo "$file is a file"
fi
done
运行脚本:
$ ./test7.sh
Desktop is a directory
Documents is a directory
Downloads is a directory
Music is a directory
Pictures is a directory
Public is a directory
Templates is a directory
test1.sh is a file
test2.sh is a file
test3.sh is a file
test4.sh is a file
test5.sh is a file
test6.sh is a file
test7.sh is a file
today.txt is a file
Videos is a directory
$
在处理目录中的文件时,常用通配符指定文件范围:
- 问号(?)代表一个字符,如
c?t
会匹配
cat
、
cot
和
cut
。
- 星号(*)代表任何字符、多个字符或无字符,如
c*t
会匹配
cat
、
caveat
和
ct
。
- 方括号内的字符集只匹配括号内的字符,如
c[au]t
会匹配
cat
和
cut
,但不匹配
cot
。
3.4.2 while循环
while
循环的格式如下:
while [ condition ] ; do
commands
done
只要指定的条件计算为
True
逻辑值,
while
循环就会继续循环;当条件为
False
时,循环停止。例如
test8.sh
脚本用于计算一个数的阶乘:
#!/bin/bash
number=$1
factorial=1
while [ $number -gt 0 ] ; do
factorial=$[ $factorial * $number ]
number=$[ $number - 1 ]
done
echo The factorial of $1 is $factorial
运行脚本:
$ ./test8.sh 5
The factorial of 5 is 120
$ ./test8.sh 6
The factorial of 6 is 720
$
while
循环完成了遍历数字系列的工作,现在可以将任何数字作为命令行参数来计算阶乘值。
while
命令的相反命令是
until
命令,它会一直迭代命令块,直到测试条件计算为
True
逻辑值。
3.5 文本操作
shell脚本的一个强大用途是快速轻松地处理大量数据。常见的命令行特性包括:
- 通配:允许在脚本中使用通配符搜索多个文件和目录。
- 参数扩展:通过在变量名周围加上花括号,如
${test}
,可以利用参数扩展,根据偏移量和长度指定变量的子字符串值。
- 读取:
read
实用程序允许逐行读取文本文件,以便使用标准文本操作工具进行处理。
- 正则表达式:使用正则表达式可以在文件中查找和替换特定字符串。
3.6 练习:编写Bash脚本来查看系统用户的密码信息
以下是具体步骤:
1. 登录到Linux图形桌面并打开命令提示符窗口。
2. 在命令提示符下,打开选择的文本编辑器,通过输入
nano pwinfo.sh
、
pico pwinfo.sh
或
vi pwinfo.sh
创建文本文件
pwinfo.sh
。
3. 在新文本文件中输入以下代码:
#!/bin/bash
# pwinfo.sh - display password information for all users
list=$(cut -d : -f 1 /etc/passwd)
for user in $list ; do
echo Password information for $user
sudo chage -l $user
echo "----------"
done
- 使用编辑器的保存命令保存文件。
-
通过输入
chmod u+x pwinfo.sh为文件赋予执行权限。 -
通过输入
./pwinfo.sh运行shell脚本。 -
在
sudo命令提示符处输入密码。
运行脚本后,应该会看到系统上所有配置用户账户的
chage
密码信息列表。
综上所述,基本的shell脚本编写允许我们将多个命令组合成一个命令运行。可以使用输出重定向将命令的输出重定向到文件,也可以使用管道将一个命令的输出重定向为另一个命令的输入数据。通过掌握上述各种技巧和方法,可以编写出功能强大、高效的Bash脚本。
4. 总结与回顾
4.1 核心要点回顾
在前面的内容中,我们详细探讨了Bash脚本编程的多个方面,下面通过一个表格来回顾核心要点:
| 编程元素 | 描述 | 示例代码 |
| ---- | ---- | ---- |
| 命令行参数 | 脚本可接收命令行传入的参数,使用
$1
、
$2
等变量获取 |
bash<br># test4.sh<br>#!/bin/bash<br>echo $1 checked in $2 days ago<br>
|
| 退出状态 | 脚本结束时返回退出状态,通过
$?
变量获取,可用
exit
命令更改 |
bash<br>$ /bin/bash<br>$ exit 120<br>$ echo $?<br>120<br>
|
| 命令替换 | 将命令输出赋给变量,有反引号和
$()
两种格式 |
bash<br>$ var1=`date`<br>$ var2=$(who)<br>
|
| 数学运算 | 整数用
$[]
,浮点用
bc
计算器 |
bash<br>result=$[ 25 * 5 ]<br>var1=$(echo "scale=4; 3.44 / 5" | bc)<br>
|
| 逻辑语句 - if | 根据条件执行命令,条件为真执行
then
部分 |
bash<br>if [ $1 -eq $2 ]<br>then<br> echo "Both values are equal!"<br>fi<br>
|
| 逻辑语句 - case | 检查变量值,匹配模式执行对应命令 |
bash<br>case $USER in<br>rich \| barbara)<br> echo "Welcome, $USER"<br> ;;<br>esac<br>
|
| 循环 - for | 遍历系列元素,依次执行命令 |
bash<br>for file in $(ls \| sort) ; do<br> if [ -d $file ]<br> then<br> echo "$file is a directory"<br> fi<br>done<br>
|
| 循环 - while | 条件为真时持续循环 |
bash<br>while [ $number -gt 0 ] ; do<br> factorial=$[ $factorial * $number ]<br> number=$[ $number - 1 ]<br>done<br>
|
| 文本操作 | 包括通配、参数扩展、
read
和正则表达式等 |
bash<br>for file in c*.txt ; do<br> # 通配示例<br> echo $file<br>done<br>
|
4.2 编程流程梳理
为了更清晰地展示Bash脚本编程的整体流程,下面是一个mermaid格式的流程图:
graph TD;
A[开始编写脚本] --> B[接收命令行参数];
B --> C{是否需要数学运算};
C -- 是 --> D[进行整数或浮点运算];
C -- 否 --> E{是否需要逻辑判断};
D --> E;
E -- 是 --> F[使用if或case语句];
E -- 否 --> G{是否需要循环操作};
F --> G;
G -- 是 --> H[使用for或while循环];
G -- 否 --> I{是否需要文本操作};
H --> I;
I -- 是 --> J[运用通配、参数扩展等];
I -- 否 --> K[脚本执行结束,返回退出状态];
J --> K;
4.3 实际应用场景
Bash脚本在实际应用中有广泛的用途,以下是一些常见场景:
-
系统管理
:自动化执行系统维护任务,如定期清理日志文件、备份数据等。
-
开发辅助
:在软件开发过程中,自动化编译、测试等流程,提高开发效率。
-
数据处理
:对大量文本数据进行筛选、转换和分析,如从日志文件中提取特定信息。
4.4 进一步学习建议
虽然我们已经掌握了Bash脚本编程的基础知识,但要成为一名熟练的脚本编写者,还需要不断学习和实践。以下是一些建议:
-
阅读优秀脚本
:学习他人编写的优秀脚本,了解不同的编程思路和技巧。
-
参与开源项目
:在开源项目中贡献代码,与其他开发者交流,提升自己的编程水平。
-
深入学习高级特性
:如函数、数组、信号处理等,进一步拓展脚本的功能。
通过不断地学习和实践,我们可以编写出更加复杂、高效的Bash脚本,为日常工作和开发带来便利。希望大家能够将所学知识运用到实际中,不断探索和创新。
超级会员免费看
1542

被折叠的 条评论
为什么被折叠?



