如何判断 Bash 字符串是否包含 Linux 上的子字符串

有时在 Linux 脚本中,您想知道一串文本是否包含特定的、较小的字符串。有很多方法可以做到这一点。我们向您展示一些简单、可靠的技术。
为什么这有用?
在字符串中搜索更小的子字符串是一个常见的要求。一个示例是从文件或人工输入中读取文本并在字符串中搜索特定子字符串,以便您的脚本可以决定下一步要做什么。它可能会在配置文件中查找标签或设备名称,或者在用户输入的一行中查找命令字符串。
Linux 用户有幸拥有许多用于处理文本的实用程序。有些内置在 Bash shell 中,有些则作为独立的实用程序或应用程序提供。 Unix 派生的操作系统具有丰富的字符串操作功能是有原因的。
有些看起来是文件的东西并不是简单的文件。它们是特殊文件,代表诸如硬件设备和系统信息源之类的东西。操作系统执行的抽象赋予它们文件的外观和特征。您可以从它们中读取信息——当然是作为文本——在某些情况下可以写入它们,但它们不是普通文件。
文本还用作终端窗口中命令的输入和输出。这允许输入和输出的重定向和管道。该功能支持将 Linux 命令序列链接在一起的能力,将一个命令的输出作为输入传递给下一个命令。
无论其来源如何,在我们收到的文本中搜索重要的词、命令、标签或其他一些指示符是处理基于文本的数据的标准部分。这是您可以包含在自己的脚本中的一组简单技术。
使用 Bash 内置函数查找子字符串
双括号“[[...]]
”字符串比较测试可用于if
语句以确定一个字符串是否包含另一个字符串。
将此脚本复制到编辑器中,并将其保存到名为“double.sh”的文件中。
#!/bin/bash
if [[ "monkey" = *"key"* ]]; then
echo "key is in monkey"
else
echo "key is not in monkey"
fi
您需要使用 chmod
命令使脚本可执行。这是使任何脚本可执行始终需要的步骤。每次创建脚本文件时都需要这样做。在每种情况下替换适当脚本的名称。
chmod +x double.sh

让我们运行脚本。
./double.sh

这是有效的,因为星号“*
”代表任何字符序列,包括无字符。如果子字符串“key”位于目标字符串中,无论其前面或后面是否有任何字符,测试都将返回 true。
在我们的示例中,子字符串前面有字符。这些由第一个星号匹配。子字符串后面没有字母,但是因为星号也不匹配任何字符,所以测试仍然通过。
为了灵活性,我们可以修改我们的脚本来处理变量而不是文字字符串。这是脚本“double2.sh”。
#!/bin/bash
string="Monkey"
substring="key"
if [[ $string = *$substring* ]]; then
echo "$substring was found in $string"
else
echo "$substring was not found in $string"
fi
让我们看看它是如何运行的。
./double2.sh

这以相同的方式工作,优点是我们可以使用变量名而不是文字字符串。将我们的小解决方案变成一个函数将提供最大的灵活性。
这是脚本“double3.sh”。
#!/bin/bash
shopt -s nocasematch
string="Monkey"
substring="Key"
capital="London"
check_substring ()
{
if [[ $1 = *$2* ]]; then
echo "$2 was found in $1"
else
echo "$2 was not found in $1"
fi
}
check_substring "Monkey" "key"
check_substring $string $substring
check_substring $string "banana"
check_substring "Wales" $capital
我们使用变量和文字字符串的组合来调用我们的 check_substring
函数。我们使用 shopt
及其 -s
(set) 选项来设置 nocasematch
,使匹配不区分大小写。
这是它的运行方式。
./double3.sh

我们也可以在 case
语句中使用将子字符串包装在星号中的技巧。这是“case.sh”。
#!/bin/bash
shopt -s nocasematch
string="Wallaby"
substring="Wall"
case $string in
*$substring*)
echo "$substring was found in $string"
;;
*)
echo "Nothing matched: $string"
;;
esac
使用 case
语句而不是很长的 if
语句可以使脚本更易于阅读和调试。如果您需要检查一个字符串是否包含许多可能的子字符串之一,case
语句将是最佳选择。
./case.sh

找到子字符串。
使用 grep 查找子字符串
除了 Bash 内置函数之外,您可能会使用的第一个文本搜索工具是 grep
。我们可以使用 grep
的先天能力在字符串中搜索字符串来查找我们的子字符串。
该脚本称为“subgrep.sh”。
#!/bin/bash
string="porridge pot"
substring="ridge"
if $(echo $string | grep -q $substring); then
echo "$substring was found in $string"
else
echo "$substring was not found in $string"
fi
该脚本使用 echo
将字符串发送到 grep
,后者会搜索子字符串。我们正在使用 -q
(安静)选项来停止 grep
将任何内容写入标准输出。
如果括号“(...)
”中命令的结果为零,则表示找到了匹配项。因为在 Bash 中零等于 true
,所以满足 if
语句并执行 then
子句。
让我们看看它的输出是什么。
./subgrep.sh

使用 sed 查找子字符串
我们也可以使用 sed
来查找子字符串。
默认情况下,sed
打印输入其中的所有文本。使用 sed -n
可以防止这种情况。唯一打印的行是匹配行。此表达式将打印任何匹配或包含 $substring 值的行。
"/$substring/p"
我们使用此处重定向 <<<
将 $string
的值提供给 sed
。这用于将值重定向到当前 shell 中的命令。它不会像管道那样调用子 shell。
第一个 -n
是测试。如果 sed
命令的输出不为零,它将返回 true
。 sed
的输出可以是非零的唯一方法是找到匹配行。如果是这种情况,则 $substring
一定已在 $string
中找到。
这是“subsed.sh”。
#!/bin/bash
string="Sweden"
substring="eden"
if [ -n "$(sed -n "/$substring/p" <<< $string)" ]; then
echo "$substring was found in $string"
else
echo "$substring was not found in $string"
fi
当我们运行脚本时,我们得到了预期的响应。
./subsed.sh

我们可以通过编辑$substring
的值来测试脚本的逻辑,使比较失败。
./subsed.sh

停止搜索,找到它
其他工具可以找到子字符串,例如 awk
和 Perl
,但是像查找子字符串这样的简单用例并不能保证它们的额外功能或增加的复杂性。特别是,使用 Bash 内置搜索子字符串快速、简单,并且不需要外部工具。