63、Bash脚本部署与编程全解析

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
  1. 使用编辑器的保存命令保存文件。
  2. 通过输入 chmod u+x pwinfo.sh 为文件赋予执行权限。
  3. 通过输入 ./pwinfo.sh 运行shell脚本。
  4. 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脚本,为日常工作和开发带来便利。希望大家能够将所学知识运用到实际中,不断探索和创新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值