geekdoc-python-zh/docs/pythonland/64.md

8.7 KiB
Raw Permalink Blame History

如何创建 Bash 脚本,带有示例代码

原文:https://python.land/the-unix-shell/creating-bash-scripts

使用 bash 脚本,您可以运行命令序列。它们防止你重复你自己,并允许你存储冗长乏味的输入命令以备后用。在本文中,您将学习如何创建 Bash 脚本。您还将学习如何读取参数、使用变量以及创建 for 循环来重复操作。

在开始创建脚本之前,确保您熟悉基本的 Linux 命令。

目录

创建一个 Bash 脚本

命令行脚本以 shebang 开始she bang 是两个字符#!的序列。在这两个字符之后,你可以命名任何解释器和一串参数,就像这样:

#!interpreter [optional arguments]

一个 shell 脚本通常基于最流行的 shell Bash因此它可以简单地变成:

#!/bin/bash

有时你会看到这个:

#!/usr/bin/env bash

使用/usr/bin/env时,提供的命令会在当前$PATH中搜索,而不是硬编码到/bin/bash位置。Bash 几乎总是出现在/bin/bash,所以第一种方法对我们来说很好。

然而,您可能想要使用这个技巧来创建一个可执行的 Python 脚本。Python 可以安装在任何地方,这取决于它的安装方式。我在/usr/bin//bin/usr/local/bin都看过,就举几个吧。如果你运行的是虚拟环境,它可以在任何地方。所以搜索$PATH是一个好的选择,因为这将从虚拟环境中找到 Python 版本。

我们稍后将创建一个实际的 shell 脚本。但是首先,我们将看看变量和 for 循环,让事情更生动一些。

Bash 变量

就像其他语言一样Bash 也有变量。Bash 中变量的一个奇特之处在于,您可以用美元符号访问它们,但却不用它来设置它们。为了澄清,这里有一个例子:

myvar="Hello world"
echo $myvar

Bash 有许多为您自动设置的保留变量。下表列出了一些更有用的方法,但并不详尽:

可变的 功能
$0 当前脚本的名称。
$1 … $9 脚本的前 9 个参数。
$# 传递给脚本的参数数量。
$@ 提供给脚本的所有参数。
$用户 运行脚本的用户的用户名。
$主机名 运行脚本的机器的主机名。
美元秒 自脚本启动以来的秒数。
$随机 每次被引用时返回一个不同的随机数。
$行号 返回 Bash 脚本中的当前行号。

Bash 保留变量

Bash 脚本参数

我们现在能够创建一个 shell 脚本,但是这个脚本将在您每次运行它时做同样的事情。我们可以通过使用论点让它变得更加有趣。

这里有个例子,叫它arguments.sh:

#!/bin/bash
echo "Hello $1, from $0"

如果我们用一个参数运行它,结果如下:

$ ./arguments.sh Weirdo
Hello Weirdo, from ./arguments.sh

Bash 所做的,是把你的整个命令分割开来,并把它分配给不太有想象力的变量$0$1$2等等。如您所见,我们命令的第一部分是脚本本身的名称。这可以派上用场,在下一节中可以看到。

创建一个安全网

在进入正题之前,我想教你一个重要的安全网。

一旦开始创建脚本,就不可避免地会出错。我们都是。脚本中一个非常常见的错误可能是灾难性的。这是未设置的变量。如果你不明白我的意思,只要继续读下去,一会儿就会明白了。

Thank you for reading my tutorials. I write these in my free time, and it requires a lot of time and effort. I use ads to keep writing these free articles, I hope you understand! Support me by disabling your adblocker on my website or, alternatively, buy me some coffee. It's much appreciated and allows me to keep working on this site!

我们可以通过使用以下命令启动脚本来防止使用未设置的变量:

set -u

仅此而已!从现在开始,当您进行替换时,您的脚本会将未设置的变量视为错误。

例如,此脚本将失败:

#!/bin/bash
set -u
rm -rf /$my_directory

输出:

$ ./test.sh                                                          
./test.sh: 3: ./test.sh: my_directory: parameter not set

那是因为我从来没有设置过$my_directory。没有set -u,它不会失败,而是忽略空变量,留给我们命令rm -rf /。我们都知道那是什么,对吧?如果由特权用户(比如root)执行,这个错误将会清除我的整个文件系统,而不是我想要删除的目录。

养成总是以set -u开始脚本的习惯。

Bash for loop

一旦掌握了 Bash for-loops命令行(尤其是脚本)的用处就会成倍增加。尽管它们看起来很吓人,但其实并没有那么难。

Bash for 循环的语法

循环的基本语法是:

for VARIABLE in A LIST
do
  command1
  command2
  commandN
done

【Bash 脚本示例

A LIST部分可以是任何东西:文件名、数字或字符串。不过,在大多数脚本中,它将是一个文件名列表,因为这是我们在 Bash 中经常使用的。现在我们知道了如何创建一个循环,让我们看看我们的第一个脚本:

#!/bin/bash

echo "You can list numbers and text like this:"

for n in 1 2 3 four
do
  echo "Number $n"
done

echo "Or specify a range of numbers:"

for n in {1..5}
do
  echo "Number $n"
done

echo "Or use the output of another command:"
for f in $(ls)
do
  echo $f
done

在上一个 for 循环中,我使用了表达式$(ls)。这会执行括号中的命令并替换结果。在这种情况下,ls被执行for 循环被输入了ls打印出的文件名。

启动 Bash 脚本

要启动这个脚本,我们可以做两件事。首先,我们可以运行它:

$ bash loop.sh

我推荐的第二种方法是使文件可执行。操作系统将知道如何执行我们的文件,因为我们的 shebang 行在顶部!通过设置文件的“执行标志”可以使文件成为可执行文件,如下所示:

$ chmod +x loop.sh

现在,您可以使用以下命令运行该脚本:

$ ./loop.sh

在我的例子中,输出是:

$ ./loop.sh
You can just list a bunch of numbers and text like this:
1
2
3
four
Or specify a range of numbers:
1
2
3
4
5
Or use the output of another command:
loop.sh
notes.txt

对您来说可能有所不同,这取决于运行脚本的目录中有哪些文件。

Bash 条件编程

有时,您只想在特定条件为真时运行命令。为此,我们在 bash 中使用了if… then… else…fi构造。

检查 bash 脚本中的参数

我们可以使用条件编程来改进我们之前的例子arguments.sh,因为它包含了一个小问题。它期望在$1中有一个名字,但不检查它是否真的有名字。让我们来解决这个问题:

https://crumb.sh/embed/fawGEMEUYGg

检查 Bash 脚本中的参数

如果这不起作用,下面是相同代码的静态版本:

#!/bin/bash
if test -z "$1"
then
  echo "Usage: $0 <Your name>"
else
  echo "Hello $1, from $0"
fi

bash 中的测试命令

test -z我们可以检查变量的长度是否为零。如果是这种情况,我们打印一些友好的使用说明:

$ ./arguments.sh
Usage: ./arguments.sh <Your name>

test 命令可以测试很多东西,所以它确实有助于条件编程。当你在命令行输入man test就可以看到完整的列表。没错,你不需要什么都用谷歌!使用手册页是成为命令行忍者的一部分!您会发现,几乎所有您可以在终端中做的事情都有一个手册页。毕竟,在过去,我们没有互联网来搜索一切…

下面是我们比较两个值以确定它们是否相同的另一个例子:

https://crumb.sh/embed/3PAwdsNPFva

比较 Bash 中的两个值

下面是静态版本,以防不起作用:

#!/bin/bash
for i in {1..10}
do
  if test $i -eq 3 
  then
    echo "I found the 3!"
  else
    echo "Not looking for the $i"
  fi
done

该循环运行 10 次迭代,每次检查$i是否等于 3。你能预测产量吗

尽管else-部分是可选的,但您总是需要以fi结尾。