如何在 Linux 中使用双括号条件测试
已发表: 2022-01-29条件测试根据逻辑表达式的结果对 Linux Bash 脚本的执行流程进行分支。 双括号条件测试大大简化了语法——但仍然有自己的陷阱。
单括号和双括号
Bash 提供了test
命令。 这使您可以测试逻辑表达式。 该表达式将返回一个表示真或假响应的答案。 返回值为零表示真正的响应。 零以外的任何值都表示错误。
使用&&
运算符在命令行上链接命令使用此功能。 仅当前一个命令成功完成时才会执行命令。
如果测试为真,将打印“是”字样。
测试 15 -eq 15 && 回显“是”
测试 14 -eq 15 && 回显“是”
单括号条件测试模仿test
命令。 它们将表达式括在括号“ [ ]
”中,并像test
命令一样操作。 事实上,它们是相同的程序,由相同的源代码创建。 唯一的操作差异是test
版本和[
版本如何处理帮助请求。
这是来自源代码:
/* 识别 --help 或 --version,但仅当在 "[" 形式,当最后一个参数不是 "]" 时。 直接使用 解析,而不是 parse_long_options,以避免接受 缩写。 POSIX 允许 "[ --help" 和 "[ --version" 具有通常的 GNU 行为,但它需要“test --help” 和 "test --version" 以状态 0 静默退出。 */
我们可以通过向test
和[
寻求帮助并检查发送到 Bash 的响应代码来查看其效果。
测试——帮助
回声$?
[ - 帮助
回声$?
test
和[
都是 shell builtins ,这意味着它们直接被烘焙到 Bash 中。 但也有一个独立的二进制版本[
。
型式试验
类型 [
哪里 [
相比之下,双括号条件测试[[
和]]
是关键字。 [[
和]]
也执行逻辑测试,但它们的语法不同。 因为它们是关键字,所以您可以使用一些在单括号版本中无法使用的简洁功能。
Bash 支持双括号关键字,但它们并非在所有其他 shell 中都可用。 例如,Korn shell 确实支持它们,但普通的旧 shell sh 不支持。 我们所有的脚本都以以下行开头:
#!/bin/bash
这确保我们调用 Bash shell 来运行脚本。
相关:如何在 Windows 10 上创建和运行 Bash Shell 脚本
内置函数和关键字
我们可以使用compgen
程序列出内置函数:
补偿-b | fmt -w 70
如果不通过fmt
管道输出,我们会得到一个很长的列表,每个内置函数都在自己的行上。 在这种情况下,将内置函数组合成一个段落会更方便。
我们可以在列表中看到test
和[
,但]
没有列出。 [
命令查找结束]
以检测它何时到达表达式的末尾,但]
不是单独的内置命令。 这只是我们给[
的一个信号,表示参数列表的结束。
要查看关键字,我们可以使用:
补偿-k | fmt -w 70
[[
和]]
关键字都在列表中,因为[[
是一个关键字,而]]
是另一个关键字。 它们是一对,就像if
和fi
以及case
和esac
一样。
当 Bash 解析脚本或命令行并检测到具有匹配的关闭关键字的关键字时,它会收集出现在它们之间的所有内容并应用关键字支持的任何特殊处理。
使用内建命令,内建命令后面的内容会像传递给任何其他命令行程序的参数一样传递给它。 这意味着脚本的作者必须特别注意变量值中的空格等内容。
壳牌通配符
双括号条件测试可以使用 shell globbing。 这意味着星号“ *
”将扩展为表示“任何东西”。
在编辑器中键入或复制以下文本并将其保存到名为“whelkie.sh”的文件中。
#!/bin/bash stringvar="惠尔基布鲁克斯" 如果 [[ "$stringvar" == *elk* ]]; 然后 echo "警告包含海鲜" 别的 echo "不含软体动物" 菲
要使脚本可执行,我们需要使用带有-x
(执行)选项的chmod
命令。 如果您想试用它们,您需要对本文中的所有脚本执行此操作。
chmod +x whelkie.sh
当我们运行脚本时,我们看到在字符串“Whelkie”中找到了字符串“elk”,而不管它周围有什么其他字符。
./whelkie.sh
需要注意的一点是,我们不会将搜索字符串用双引号括起来。 如果这样做,则不会发生 globbing。 搜索字符串将按字面意思处理。
允许使用其他形式的 shell globbing。 问号“ ?
” 将匹配单个字符,单个方括号用于表示字符范围。 例如,如果您不知道使用哪种情况,您可以用一个范围涵盖这两种可能性。
#!/bin/bash stringvar="让-克劳德·范·克拉姆" 如果 [[ "$stringvar" == *[cC]lam* ]]; 然后 echo "警告包含海鲜。" 别的 echo "不含软体动物。" 菲
将此脚本另存为“damme.sh”并使其可执行。 当我们运行它时,条件语句解析为真,并且执行 if 语句的第一个子句。
./damme.sh
引用字符串
我们之前提到过用双引号括起来的字符串。 如果你这样做,shell globbing 将不会发生。 尽管约定说这是一种很好的做法,但在使用[[
和]]
时,即使字符串变量包含空格,也不需要将它们括在引号中。 看下一个例子。 $stringvar
和$surname
字符串变量都包含空格,但在条件语句中都没有引用。
#!/bin/bash stringvar="范达姆" 姓氏="范达姆" 如果 [[ $stringvar == $surname ]]; 然后 echo "姓氏匹配。" 别的 echo "姓氏不匹配。" 菲
将其保存到名为“surname.sh”的文件中并使其可执行。 使用以下命令运行它:
./surname.sh
尽管两个字符串都包含空格,但脚本成功并且条件语句解析为 true。 这在处理包含空格的路径和目录名称时很有用。 在这里,如果变量包含有效的目录名称,则-d
选项返回 true。
#!/bin/bash dir="/home/dave/Documents/需要工作" 如果 [[ -d ${dir} ]]; 然后 echo "目录已确认" 别的 echo "找不到目录" 菲
如果您更改脚本中的路径以反映您自己计算机上的目录,将文本保存到名为“dir.sh”的文件中并使其可执行,您可以看到这是可行的。
./dir.sh
相关:如何在 Bash 中使用变量
文件名通配问题
[ ]
和[[ ]]
之间的一个有趣区别与包含通配符的文件名有关。 “*.sh”形式将匹配所有脚本文件。 除非只有一个脚本文件,否则使用单括号[ ]
会失败。 查找多个脚本会引发错误。
这是带有单括号条件的脚本。
#!/bin/bash 如果 [ -a *.sh ]; 然后 echo "找到一个脚本文件" 别的 echo "没有找到脚本文件" 菲
我们将此文本保存到“script.sh”并使其可执行。 我们检查了目录中有多少脚本,然后运行脚本。
ls
./script.sh
Bash 抛出一个错误。 我们删除了除一个脚本文件之外的所有文件并再次运行该脚本。
ls
./script.sh
条件测试返回 true 并且脚本不会导致错误。 编辑脚本以使用双括号提供了第三种行为。
#!/bin/bash 如果 [[ -a *.sh ]]; 然后 echo "找到一个脚本文件" 别的 echo "没有找到脚本文件" 菲
我们将其保存到一个名为“dscript.sh”的文件中并使其可执行。 在包含许多脚本的目录中运行此脚本不会引发错误,但该脚本无法识别任何脚本文件。
使用双括号的条件语句仅在您在目录中有一个实际名为“*.sh”的文件的不太可能的情况下解析为 true。
./dscript.sh
逻辑与和或
双括号让您可以使用&&
和||
作为逻辑 AND 和 OR 运算符。
此脚本应将条件语句解析为 true,因为 10 确实等于 10 ,而25 小于 26。
#!/bin/bash 第一个=10 秒=25 如果 [[ 第一个 -eq 10 && 第二个 -lt 26 ]]; 然后 echo "条件满足" 别的 echo "条件失败" 菲
将此文本保存到名为“and.sh”的文件中,使其可执行,然后使用以下命令运行它:
./and.sh
脚本按照我们的预期执行。
这次我们将使用||
操作员。 条件语句应该解析为真,因为虽然 10 不大于 15,但 25 仍然小于 26。只要第一次比较或第二次比较为真,条件语句作为一个整体解析为真。
将此文本保存为“or.sh”并使其可执行。
#!/bin/bash 第一个=10 秒=25 如果 [[ 第一个 -gt 15 || 第二-lt 26]]; 然后 echo "条件满足。" 别的 echo "条件失败。" 菲
./或.sh
正则表达式
双括号条件语句允许使用=~
运算符,它将字符串中的正则表达式搜索模式应用于语句的另一半。 如果满足正则表达式,则认为条件语句为真。 如果正则表达式找不到匹配项,则条件语句解析为 false。
相关:如何在 Linux 上使用正则表达式(regexes)
将此文本保存到名为“regex.sh”的文件中,并使其可执行。
#!/bin/bash 话=“一二三” WordsandNumbers="一 1 二 2 三 3" email="[email protected]" 掩码 1="[0-9]" mask2="[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+.[A-Za-z]{2,4}" 如果 [[ $words =~ $mask1 ]]; 然后 echo "\"$words\" 包含数字。" 别的 echo "在 \"$words\" 中找不到数字。" 菲 如果 [[ $WordsandNumbers =~ $mask1 ]]; 然后 echo "\"$WordsandNumbers\" 包含数字。" 别的 echo "在 \"$WordsandNumbers\" 中找不到数字。" 菲 如果 [[ $email =~ $mask2 ]]; 然后 echo "\"$email\" 是一个有效的电子邮件地址。" 别的 echo "无法解析 \"$email\"。" 菲
第一组双括号使用字符串变量$mask1
作为正则表达式。 这包含零到九范围内所有数字的模式。 它将这个正则表达式应用于$words
字符串变量。
第二组双括号再次使用字符串变量$mask1
作为正则表达式,但这次它与$WordsandNumbers
字符串变量一起使用。
最后一组双括号在字符串变量$mask2
中使用了更复杂的正则表达式掩码。
- [A-Za-z0-9._%+-]+ :匹配任何大写或小写字母,或从零到九的任何数字,或句点、下划线、百分号或加号或减号. “
[]
”之外的“+
”表示重复这些匹配以找到尽可能多的字符。 - @ :这仅匹配“@”字符。
- [A-Za-z0-9.-]+ :这匹配任何大写或小写字母,或从零到九的任何数字,或句点或连字符。 “
[ ]
”之外的“+
”表示对找到的字符重复这些匹配。 - . : 这匹配“.” 仅字符。
- [A-Za-z]{2,4} :匹配任何大写或小写字母。 “
{2,4}
”表示至少匹配两个字符,最多匹配四个。
综上所述,正则表达式掩码将检查电子邮件地址的格式是否正确。
将脚本文本保存到名为“regex.sh”的文件中并使其可执行。 当我们运行脚本时,我们会得到这个输出。
./regex.sh
第一个条件语句失败,因为正则表达式正在查找数字,但$words
字符串变量中保存的值中没有数字。
第二个条件语句成功,因为$WordsandNumbers
字符串变量确实包含数字。
最后的条件语句成功了——也就是说,它解析为真——因为电子邮件地址的格式正确。
只有一个条件
双括号条件测试为您的脚本带来了灵活性和易读性。 只要能够在条件测试中使用正则表达式就可以证明学习如何使用[[
和]]
。
只需确保脚本调用支持它们的 shell,例如 Bash。
相关:你需要知道的 15 个特殊字符