今天我们将讨论 bash 脚本。 这 - ,为 bash shell 编写。 还有其他 shell,例如 zsh、tcsh、ksh,但我们将重点关注 bash。 本材料适用于所有人,唯一的条件是能够在其中工作 Linux.
命令行脚本是相同命令的集合,这些命令可以从键盘输入、收集到文件中并通过某些共同目的统一起来。 在这种情况下,团队的工作结果可以具有独立价值,也可以作为其他团队的输入数据。 脚本是自动执行频繁执行的操作的有效方法。
因此,如果我们谈论命令行,它允许您通过输入用分号分隔的命令来一次执行多个命令:
pwd ; whoami 事实上,如果您在终端中尝试过此操作,那么您的第一个涉及两个命令的 bash 脚本已经编写完毕。 它的工作原理是这样的。 团队第一 pwd 显示当前工作目录的信息,然后命令 whoami显示有关您登录的用户的信息。
使用这种方法,您可以在一行上组合任意数量的命令,唯一的限制是可以传递给程序的参数的最大数量。 您可以使用以下命令定义此限制:
getconf ARG_MAX命令行是一个很棒的工具,但是每次需要时都必须向其中输入命令。 如果我们将一组命令写入一个文件并简单地调用该文件来执行它们会怎么样? 事实上,我们所说的文件称为命令行脚本。
bash 脚本如何工作
使用命令创建一个空文件 touch。 它的第一行需要指示我们将使用哪个 shell。 我们感兴趣的是 bash,所以文件的第一行将是:
#!/bin/bash 该文件中的其他行使用井号来指示 shell 不处理的注释。 然而,第一行是一个特殊情况,有一个散列后面跟着一个感叹号(这个序列称为 )和路径 bash,向系统表明该脚本是专门为 bash.
Shell 命令由换行符分隔,注释由井号分隔。 它看起来是这样的:
#!/bin/bash
# This is a comment
pwd
whoami在这里,就像在命令行上一样,您可以将命令写在一行上,并用分号分隔。 但是,如果将命令写在不同的行上,文件将更易于阅读。 无论如何,外壳都会处理它们。
设置脚本文件权限
保存文件并为其命名 myscript,bash脚本的创建工作就快完成了。 现在剩下的就是使该文件可执行,否则,如果您尝试运行它,您将遇到错误 Permission denied.

尝试运行权限配置不正确的脚本文件
让我们使文件可执行:
chmod +x ./myscript现在让我们尝试执行它:
./myscript设置权限后,一切都会正常进行。

成功运行bash脚本
消息输出
将文本输出到控制台 Linux 该命令已执行 echo。 让我们利用这一事实的知识并编辑我们的脚本,为其中已有的命令输出的数据添加解释:
#!/bin/bash
# our comment is here
echo "The current directory is:"
pwd
echo "The user logged in is:"
whoami这是运行更新的脚本后发生的情况。

从脚本输出消息
现在我们可以使用命令显示解释性注释 echo如果您不知道如何使用工具编辑文件, Linux或者之前从未见过该团队。 echo, 看一眼 材料。
使用变量
变量允许您在脚本文件中存储信息(例如命令的结果),以供其他命令使用。
执行单个命令而不存储其结果并没有什么问题,但这种方法的功能非常有限。
bash 脚本中可以使用两种类型的变量:
- 环境变量
- 用户变量
环境变量
有时 shell 命令需要处理一些系统数据。 以下是如何显示当前用户的主目录的示例:
#!/bin/bash
# display user home
echo "Home for the current user is: $HOME" 请注意,我们可以使用系统变量 $HOME 用双引号括起来,这不会阻止系统识别它。 这就是运行上述场景时得到的结果。

在脚本中使用环境变量
如果您需要在屏幕上显示美元符号怎么办? 让我们试试这个:
echo "I have $1 in my pocket" 系统将检测带引号的字符串中的美元符号,并假设我们引用了一个变量。 该脚本将尝试显示未定义变量的值 $1。 这不是我们需要的。 该怎么办?
在这种情况下,在美元符号之前使用转义字符(反斜杠)会有所帮助:
echo "I have $1 in my pocket"该脚本现在将准确输出预期的内容。

使用转义序列打印美元符号
用户变量
除了环境变量之外,bash 脚本还允许您在脚本中定义和使用自己的变量。 此类变量将保留一个值,直到脚本完成执行。
与系统变量一样,可以使用美元符号访问用户变量:
TNW-CUS-FMP - 我们的服务可享受 10% 折扣的促销代码,可在 7 天内激活
#!/bin/bash
# testing variables
grade=5
person="Adam"
echo "$person is a good boy, he is in grade $grade"这就是运行这样的脚本后发生的情况。

脚本中的自定义变量
命令替换
bash 脚本最有用的功能之一是能够从命令输出中提取信息并将其分配给变量,从而允许您在脚本文件中的任何位置使用此信息。
这可以通过两种方式完成。
- 使用反引号“`”
- 按设计
$()
使用第一种方法时,请注意不要用单引号代替反引号。 该命令必须包含在两个这样的图标中:
mydir=`pwd`在第二种方法中,同样的事情是这样写的:
mydir=$(pwd)脚本最终可能看起来像这样:
#!/bin/bash
mydir=$(pwd)
echo $mydir 在其运行过程中,命令的输出 pwd将被保存在变量中 mydir,其中的内容,使用命令 echo,将转到控制台。

将命令结果保存在变量中的脚本
数学运算
要在脚本文件中执行数学运算,您可以使用类似的结构 $((a+b)):
#!/bin/bash
var1=$(( 5 + 5 ))
echo $var1
var2=$(( $var1 * 2 ))
echo $var2 
脚本中的数学运算
if-then 控制结构
在某些场景下,您需要控制命令执行的流程。 例如,如果某个值大于 XNUMX,则需要执行一项操作,否则执行另一项操作。 这适用于很多情况,这里控制结构会帮助我们 if-then。 最简单的形式如下所示:
if команда
then
команды
fi这是一个工作示例:
#!/bin/bash
if pwd
then
echo "It works"
fi 在这种情况下,如果执行命令 pwd将成功完成,控制台中将显示文本“it Works”。
让我们利用已有的知识编写一个更复杂的脚本。 假设我们需要在以下位置找到某个用户 /etc/passwd,如果您设法找到它,请报告它存在。
#!/bin/bash
user=likegeeks
if grep $user /etc/passwd
then
echo "The user $user Exists"
fi这就是运行该脚本后发生的情况。

Поискпользователя
这里我们使用了命令 grep在文件中搜索用户 /etc/passwd。 如果团队 grep你不熟悉的可以查看它的描述 .
在此示例中,如果找到用户,脚本将显示相应的消息。 如果找不到用户怎么办? 在这种情况下,脚本将简单地完成执行,而不告诉我们任何事情。 我们也希望他能告诉我们这一点,以便我们改进代码。
if-then-else 控制结构
为了使程序能够报告成功搜索和失败的结果,我们将使用以下结构 if-then-else。 它的工作原理如下:
if команда
then
команды
else
команды
fi 如果第一个命令返回零,这意味着它执行成功,条件将为真,并且不会沿着分支继续执行 else。 否则,如果返回非零的值(这将指示失败或错误结果),则后面的命令 else.
让我们编写以下脚本:
#!/bin/bash
user=anotherUser
if grep $user /etc/passwd
then
echo "The user $user Exists"
else
echo "The user $user doesn’t exist"
fi 他的处决付诸东流 else.

使用 if-then-else 结构运行脚本
好吧,让我们继续问自己更复杂的条件。 如果您需要检查的不是一个条件而是多个条件怎么办? 例如,如果找到所需的用户,则应显示一条消息,如果满足某些其他条件,则应显示另一条消息,等等。 在这种情况下,嵌套条件会对我们有所帮助。 它看起来像这样:
if команда1
then
команды
elif команда2
then
команды
fi 如果第一个命令返回零,表明执行成功,则将执行第一个块中的命令 then,否则,如果第一个条件为假并且第二个命令返回零,则将执行第二个代码块。
#!/bin/bash
user=anotherUser
if grep $user /etc/passwd
then
echo "The user $user Exists"
elif ls /home
then
echo "The user doesn’t exist but anyway there is a directory under /home"
fi 例如,在这样的脚本中,您可以使用以下命令创建新用户 useradd,如果搜索没有产生结果,或者做其他有用的事情。
数字比较
在脚本中,您可以比较数值。 下面是相关命令的列表。
n1 -eq n2返回真,如果n1是n2.
n1 -ge n2返回真,如果n1大于或等于n2.
n1 -gt n2返回真,如果n1更多n2.
n1 -le n2返回真,如果n1小于或等于n2.
n1 -lt n2如果 n1 小于则返回 truen2.
n1 -ne n2返回真,如果n1不平等n2.
作为示例,让我们尝试一下比较运算符之一。 请注意,表达式括在方括号内。
#!/bin/bash
val1=6
if [ $val1 -gt 5 ]
then
echo "The test value $val1 is greater than 5"
else
echo "The test value $val1 is not greater than 5"
fi这就是该命令将输出的内容。

脚本中数字的比较
变量值 val1大于5,分支最终被执行 then比较运算符和相应的消息将显示在控制台中。
字符串比较
脚本还可以比较字符串值。 比较运算符看起来很简单,但是字符串比较操作有一定的特点,我们将在下面介绍。 这是运营商列表。
str1 = str2测试字符串是否相等,如果字符串相同则返回 true。
str1 != str2如果字符串不相同,则返回 true。
str1 < str2返回真,如果str1少于str2.
str1 > str2返回真,如果str1超过str2.
-n str1如果长度返回 truestr1零以上。
-z str1如果长度返回 truestr1等于零。
以下是比较脚本中字符串的示例:
#!/bin/bash
user ="likegeeks"
if [$user = $USER]
then
echo "The user $user is the current logged in user"
fi执行脚本的结果是,我们得到以下结果。

比较脚本中的字符串
这是字符串比较的一个值得一提的功能。 即,“">”和“<”运算符必须使用反斜杠转义,否则脚本将无法正常工作,但不会出现错误消息。 该脚本将“>”符号解释为输出重定向命令。
使用这些运算符的代码如下所示:
#!/bin/bash
val1=text
val2="another text"
if [ $val1 > $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi这是脚本的结果。

字符串比较,给出警告
请注意,该脚本虽然被执行,但会发出警告:
./myscript: line 5: [: too many arguments 为了摆脱这个警告,我们得出结论 $val2 用双引号括起来:
#!/bin/bash
val1=text
val2="another text"
if [ $val1 > "$val2" ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi现在一切都按其应有的方式进行。

字符串比较
">" 和"<" 运算符的另一个功能是它们如何处理大写和小写字符。 为了理解这个功能,我们准备一个包含以下内容的文本文件:
Likegeeks
likegeeks 让我们给它起个名字来保存它 myfile,然后在终端中运行以下命令:
sort myfile它将对文件中的行进行排序,如下所示:
likegeeks
Likegeeks 团队 sort默认情况下,字符串按升序排序,即我们示例中的小写字母小于大写字母。 现在让我们准备一个脚本来比较相同的字符串:
#!/bin/bash
val1=Likegeeks
val2=likegeeks
if [ $val1 > $val2 ]
then
echo "$val1 is greater than $val2"
else
echo "$val1 is less than $val2"
fi如果你运行它,你会发现一切都是相反的——小写字母现在比大写字母大。

排序命令和比较脚本文件中的字符串
在比较命令中,大写字母比小写字母小。 这里的字符串比较是通过比较字符的 ASCII 代码来完成的,因此排序顺序取决于字符代码。
团队 sort依次使用系统语言设置中指定的排序顺序。
文件检查
也许以下命令在 bash 脚本中最常用。 它们允许您检查有关文件的各种条件。 以下是这些命令的列表。
-d file检查文件是否存在并且是目录。
-e file检查文件是否存在。
-f file检查文件是否存在以及是否是文件。
-r file检查文件是否存在并且可读。
-s file П检查文件是否存在且不为空。
-w file检查文件是否存在并且可写。
-x file检查文件是否存在并且可执行。
file1 -nt file2检查是否较新file1比file2.
file1 -ot file2检查是否较老file1比file2.
-O file检查文件是否存在并且由当前用户拥有。
-G file检查文件是否存在以及其组ID是否与当前用户的组ID匹配。
这些命令以及今天讨论的许多其他命令都很容易记住。 它们的名字是各种单词的缩写,直接表明它们执行的检查。
让我们在实践中尝试其中一个命令:
#!/bin/bash
mydir=/home/likegeeks
if [ -d $mydir ]
then
echo "The $mydir directory exists"
cd $ mydir
ls
else
echo "The $mydir directory does not exist"
fi对于现有目录,此脚本将显示其内容。

列出目录的内容
我们相信您可以自己尝试其余命令;它们都是根据相同的原理使用的。
结果
今天我们讨论了如何开始编写 bash 脚本并涵盖了一些基本知识。 事实上,bash 编程的话题很大。 本文是由 11 份材料组成的大型系列的第一部分的翻译。 如果您现在想继续,这里是这些材料的原始列表。 为了方便起见,您刚刚阅读的翻译内容包含在此处。
- — 这里我们讨论如何开始创建 bash 脚本,考虑变量的使用,描述条件结构、计算、数字、字符串的比较以及查找文件信息。
- — 这里揭示了使用 for 和 while 循环的功能。
- — 本材料专门介绍可传递给脚本的命令行参数和键,以及处理用户输入的数据和可从文件中读取的数据。
- - 这里我们讨论文件描述符和使用它们,关于输入、输出、错误流以及输出重定向。
- 本材料专门讨论信号 Linux它们在脚本中进行处理,并按计划运行脚本。
- — 在这里您可以了解如何在脚本和开发库中创建和使用函数。
- — 本文致力于使用 sed 流式文本编辑器。
- — 本材料专门介绍 awk 数据处理语言的编程。
- — 在这里您可以阅读有关在 bash 脚本中使用正则表达式的信息。
- — 以下是处理可发送给用户的消息的技术,以及磁盘监视的方法。
- — 本材料专用于 Expect 工具,您可以使用该工具自动与交互式实用程序进行交互。 特别是,我们正在讨论 Expect 脚本及其与 bash 脚本和其他程序的交互。
我们认为本系列文章的一大优点是,它从最基础的内容开始,适合任何级别的用户,逐步深入到相当严肃的主题,让每个人都有机会在命令行脚本创建领域取得进步。 Linux.
亲爱的读者们! 我们请 bash 编程大师谈论他们如何达到掌握的高度,分享他们的秘密,我们期待收到那些刚刚编写第一个脚本的人的印象。
只有注册用户才能参与调查。 拜托
我应该翻译该系列文章的其余部分吗?
是的!
不需要不需要
1030 位用户投票。 106 名用户弃权。
来源: habr.com
