9 个 Bash 脚本示例让您开始使用 Linux

已发表: 2022-07-05
笔记本电脑屏幕上的 Linux 终端。
fatmawati achmad zaenuri/Shutterstock.com

如果您刚开始在 Linux 上编写 Bash 脚本,那么扎实掌握基础知识将对您有利。 它们是更深入的知识和更高的脚本技能的基础。

记住,让你的脚本可执行

要让 shell 执行脚本,脚本必须具有可执行文件权限集。 没有这个,你的脚本只是一个文本文件。 有了它,它仍然是一个文本文件,但 shell 知道它包含指令,并会在脚本启动时尝试执行它们。

编写脚本的全部意义在于它们可以运行,所以第一步是要知道如何让 Linux 知道你的脚本应该被认为是可执行的。

chmod命令让我们设置文件权限。 可以使用 +x 标志设置执行权限。

 chmod +x script1.sh 

使脚本可执行

您需要对每个脚本执行此操作。 将“script1.sh”替换为您的脚本名称。

1. 奇怪的第一行是什么?

脚本的第一行告诉 shell 应该调用哪个解释器来运行该脚本。 第一行必须以 shebang 开头,“#!”,也称为 hashbang。 这 ”#!” 告诉 shell 这一行包含脚本所针对的解释器的路径和名称。

这很重要,因为如果您编写了要在 Bash 中运行的脚本,您不希望它被不同的 shell 解释。 可能存在不兼容的情况。 与大多数 shell 一样,Bash 有自己的语法和功能,而其他 shell 没有,或者以不同的方式实现。

当您运行脚本时,当前 shell 打开脚本并确定应该使用哪个 shell 或解释器来执行该脚本。 然后它启动那个 shell 并将脚本传递给它。

 #!/bin/bash

echo 在 $SHELL 中运行

该脚本的第一行可以读作“使用位于 /bin/bash 的解释器来运行此脚本”。

脚本中唯一的一行将$SHELL环境变量中保存的值写入终端屏幕。 这证实了使用 Bash 执行脚本。

 ./script1.sh 

识别脚本在其下运行的 shell

作为一个小技巧,我们可以证明脚本被传递给我们选择的任何解释器。

 #!/bin/cat
所有文本行都传递给 cat 命令
并打印在终端窗口中。 那包含着
舍邦线。
 脚本2.sh 

通过将脚本传递给 cat 命令来运行脚本

此脚本由当前 shell 启动并传递给cat命令。 cat命令“运行”脚本。

像这样编写你的 shebangs 假设你知道 shell 或其他解释器在目标机器上的位置。 99% 的情况下,这都很好。 但是有些人喜欢对冲他们的赌注并像这样写他们的shebangs:

 #!/usr/bin/env bash

echo 在 $SHELL 中运行
脚本3.sh 

运行搜索 shell 的脚本

当脚本启动时,shell 会搜索命名 shell 的位置。 如果 shell 恰好位于非标准位置,这种方法可以避免“错误解释器”错误。

别听,他在说谎!

在 Linux 中,总是有不止一种方法可以给猫剥皮或证明作者的错误。 完全符合事实的是,有一种方法可以在没有 shebang 的情况下运行脚本,并且不让它们可执行。

如果您启动要执行脚本的 shell 并将脚本作为命令行参数传递,则 shell 将启动并运行脚本——无论它是否可执行。 因为您在命令行上选择了 shell,所以不需要 shebang。

这是整个脚本:

 echo "我被处决了" $SHELL

我们将使用ls来查看该脚本确实不可执行,并使用该脚本的名称启动 Bash:

 ls
 bash script4.sh 

运行没有可执行文件权限集且没有 shebang 的脚本

还有一种方法可以让当前shell 运行脚本,而不是专门为执行脚本而启动的 shell。 如果使用source命令,可以缩写为单个句点“ . “,您的脚本由您当前的 shell 执行。

因此,要在没有 shebang、没有可执行文件权限且不启动另一个 shell 的情况下运行脚本,您可以使用以下任一命令:

 源脚本4.sh
 . 脚本4.sh 

在当前 shell 中运行脚本

尽管这是可能的,但不建议将其作为一般解决方案。 有缺点。

如果脚本不包含 shebang,则您无法判断它是为哪个 shell 编写的。 一年后你会记得吗? 如果脚本没有设置可执行权限, ls命令不会将其识别为可执行文件,也不会使用颜色将脚本与纯文本文件区分开来。

相关:命令行:为什么人们仍然为它们烦恼?

2. 打印文本

向终端写入文本是一项常见要求。 一点视觉反馈会有很长的路要走。

对于简单的消息, echo命令就足够了。 它允许对文本进行一些格式化,也允许您使用变量。

 #!/bin/bash

echo 这是一个简单的字符串。
echo "这是一个包含'单引号'的字符串,所以它用双引号括起来。"
echo "这将打印用户名:" $USER
echo -e "-e 选项让我们使用\n格式化指令\n分割字符串。"
 ./script5.sh 

使用 echo 命令写入终端窗口的脚本

printf命令为我们提供了更大的灵活性和更好的格式化功能,包括数字转换。

此脚本使用三个不同的数字基数打印相同的数字。 十六进制版本也被格式化为以大写形式打印,前导零和三位数的宽度。

 #!/bin/bash

printf "十进制:%d,八进制:%o,十六进制:%03X\n" 32 32 32
 ./script6.sh 

使用 printf 转换和格式化数字的脚本

请注意,与echo不同,您必须告诉printf以“ \n ”标记开始新行。

3. 创建和使用变量

变量允许您在程序中存储值并操作和使用它们。 您可以创建自己的变量或使用环境变量作为系统值。

 #!/bin/bash

millennium_text="千禧年以来的岁月:"

current_time=$(日期'+%H:%M:%S')
todays_date=$( 日期 '+%F' )
年=$(日期'+%Y')

echo "当前时间:" $current_time
echo "今天的日期:" $todays_date

years_since_Y2K=$(( 年 - 2000 ))

回声 $millennium_text $years_since_Y2K

此脚本创建一个名为millennium_text的字符串变量。 它包含一行文本。

然后它创建三个数值变量。

  • current_time变量被初始化为脚本执行的时间。
  • todays_date变量设置为脚本运行的日期。
  • year变量保存当前年份。

要访问存储在变量中的,请在其名称前加上美元符号“$”。

 ./script7.sh 

使用变量计算时间段的脚本

该脚本打印时间和日期,然后计算自千禧年以来已经过去了多少年,并将其存储在years_since_Y2K变量中。

最后,它打印包含在millennium_text变量中的字符串和存储在years_since_Y2K中的数值。

相关:如何在 Bash 中使用变量

4. 处理用户输入

要允许用户输入脚本将使用的值,您需要能够捕获用户的键盘输入。 Bash read命令允许 ut 做到这一点。 这是一个简单的例子。

 #!/bin/bash

echo "输入一个数字并点击\"Enter\""
读取用户编号 1;
echo "输入另一个数字并点击 \"Enter\""
读取用户编号2;

printf "你输入了:%d 和 %d\n" $user_number1 $user_number2
printf "把它们加在一起:%d\n" $((user_number1 + user_number2))

该脚本提示输入两个数字。 它们从键盘读取并存储在两个变量user_number1user_number2中。

该脚本将数字打印到终端窗口,将它们加在一起,然后打印总数。

 ./script8.sh 

使用 read 命令捕获用户输入

我们可以使用-p (提示)选项将提示组合到read命令中。

 #!/bin/bash

read -p "输入一个数字并点击\"Enter\" " user_number1;
read -p "输入另一个数字并点击\"Enter\" " user_number2;

printf "你输入了:%d 和 %d\n" $user_number1 $user_number2
printf "把它们加在一起:%d\n" $((user_number1 + user_number2))

这使事情更整洁,更容易阅读。 易于阅读的脚本也更易于调试。

 ./script9.sh 

使用 read 命令和 -p(提示)选项捕获用户输入

该脚本现在的行为略有不同。 用户输入与提示位于同一行。

要捕获键盘输入而不将其回显到终端窗口,请使用-s (静默)选项。

 #!/bin/bash

read -s -p "输入您的密码并点击 \"Enter\" " secret_PIN;

printf "\nShhh ... 它是 %d\n" $secret_PIN
 ./script10.sh 

捕获用户输入而不将其写入终端窗口

输入值被捕获并存储在一个名为secret_PIN的变量中,但是当用户键入它时它不会回显到屏幕上。 之后你用它做什么取决于你。

5.接受参数

有时接受用户输入作为命令行参数比让脚本等待输入更方便。 将值传递给脚本很容易。 它们可以在脚本中被引用,就像它们是任何其他变量一样。

第一个参数变为变量$1 ,第二个参数变为变量$2 ,依此类推。 变量$0始终保存脚本的名称,变量$#保存命令行中提供的参数数量。 变量$@是一个包含所有命令行参数的字符串。

 #!/bin/bash

printf "这个脚本被调用:%s\n" $0
printf "你使用了 %d 个命令行参数\n" $#

# 循环遍历变量
对于“$@”中的参数; 做
  回声“$参数”
完毕

echo "参数 2 是:" $2

该脚本使用$0$#来打印一些信息。 然后使用?@循环所有命令行参数。 它使用$2来展示如何访问单个特定的参数值。

 ./script11.sh 

在脚本中使用命令行参数

将几个单词用引号“””括起来,将它们组合成一个参数。

6. 从文件中读取数据

知道如何从文件中读取数据是一项很棒的技能。 我们可以在 Bash 中使用 while 循环来做到这一点。

 #!/bin/bash

行数=0

而 IFS='' 读取 -r LinefromFile || [[ -n "${LinefromFile}" ]]; 做

  ((线数++))
  echo "读取行 $LineCount: ${LinefromFile}"

完成 <"$1"

我们将希望脚本处理的文件的名称作为命令行参数传递。 这将是唯一的参数,因此在脚本中$1将保存文件名。 我们将该文件重定向到while循环中。

如何在 Linux Bash 脚本中逐行处理文件
相关如何在 Linux Bash 脚本中逐行处理文件

while循环使用IFS=''赋值将内部字段分隔符设置为空字符串。 这可以防止read命令在空白处拆分行。 只有行尾的回车才被认为是真正的行尾。

[[ -n "${LinefromFile}" ]]子句满足文件中最后一行不以回车符结尾的可能性。 即使没有,最后一行也将被正确处理并被视为常规的 POSIX 兼容行。

 ./script12.sh 闪烁.txt 

使用脚本从文件中读取文本

7. 使用条件测试

如果您希望脚本针对不同的条件执行不同的操作,则需要执行条件测试。 双括号测试语法起初提供了大量的选项。

 #!/bin/bash

价格=$1

如果 [[ 价格 -ge 15 ]];
然后
  回声“太贵了。”
别的
  回声“买!”
菲

Bash 提供了一整套比较运算符,可让您确定诸如文件是否存在、是否可以读取文件、是否可以写入文件以及目录是否存在等内容。

它还对等于-qe 、大于-gt 、小于或等于-le等进行了数值测试,尽管您也可以使用熟悉的==>=<=表示法。

 ./script13.sh 13
 ./script13.sh 14
 ./script13.sh 15
 ./script13.sh 16 

运行带有条件测试的脚本

8. for 循环的威力

一遍又一遍地重复动作最好使用循环来完成。 for循环允许您多次运行循环。 这可能达到一个特定的数字,或者可能直到循环通过项目列表。

 #!/bin/bash

对于 (( i=0; i<=$1; i++ ))
做
  echo "C 风格的 for 循环:" $i
完毕

对于我在 {1..4}
做
  echo "For 循环范围:" $i
完毕

对于 i 在 "零" "一" "二" "三"
做
  echo "带有单词列表的 For 循环:" $i
完毕

网站="如何极客"

对于我在 $website
做
  echo "带有单词集合的 For 循环:" $i
完毕

所有这些循环都是for循环,但它们使用不同类型的循环语句和数据。

 ./script14.sh 3 

使用四种不同类型的 for 循环运行脚本

第一个循环是经典的 C 风格for循环。 循环计数器i初始化为零,并随着循环的每个循环递增。 当i的值小于或等于$1中保存的值时,循环将继续运行。

第二个循环处理从 1 到 4 的数字范围。第三个循环处理一个单词列表。 虽然有更多的词要处理,但循环会不断重复。

最后一个循环遍历字符串变量中的单词列表。

9. 功能

函数允许您将代码段封装到命名例程中,这些例程可以从脚本中的任何位置调用。

假设我们希望从文件中读取行的脚本对每一行进行某种处理。 将该代码包含在函数中会很方便。

 #!/bin/bash

行数=0

函数 count_words() {
  printf "%d 行中的 %d 个单词\n" $(echo $1 | wc -w) $2
}

而 IFS='' 读取 -r LinefromFile || [[ -n "${LinefromFile}" ]]; 做

  ((线数++))
  count_words "$LinefromFile" $LineCount

完成 <"$1"

count_words "这不在循环中" 99

我们通过添加一个名为count_words的函数来修改我们的文件读取程序。 它是在我们需要使用它之前定义的。

函数定义以单词function开头。 接下来是我们函数的唯一名称,后跟括号“ () ”。 函数的主体包含在大括号“{}”中。

函数定义不会导致任何代码被执行。 在调用函数之前,函数中的任何内容都不会运行。

count_words函数打印一行文本中的单词数和行号。 这两个参数被传递到函数中,就像参数被传递到脚本中一样。 第一个参数成为函数变量$1 ,第二个参数成为函数变量$2 ,依此类推。

while循环从文件中读取每一行并将其与行号一起传递给count_words函数。 为了表明我们可以从脚本中的不同位置调用该函数,我们在while循环之外再次调用它。

 ./script15.sh 闪烁.txt 

运行使用函数的脚本

不要害怕学习曲线

脚本是有益的和有用的,但很难进入。 一旦掌握了一些可重用的技术,您将能够相对轻松地编写有价值的脚本。 然后您可以查看更高级的功能。

在跑步之前先步行,并花时间享受旅程。

相关: 10 个适合初学者的基本 Linux 命令