shell 脚本中不区分大小写的子字符串搜索

Mig*_*que 23 shell string shell-script

如何编写一个 shell 脚本来对命令输出进行不区分大小写的子字符串匹配?

ste*_*ver 53

如果您设置了shell 选项,您可以bash使用正则表达式运算符进行本地不区分大小写的子字符串匹配。例如=~nocasematch

s1="hElLo WoRlD"
s2="LO"

shopt -s nocasematch

[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
match

s1="gOoDbYe WoRlD"
[[ $s1 =~ $s2 ]] && echo "match" || echo "no match"
no match
Run Code Online (Sandbox Code Playgroud)

  • 哈哈!晦涩的shell知识点。 (6认同)
  • 此选项也会影响简单匹配运算符。`[[ XYZ == xyz ]] && echo "match"` => `match` (4认同)

Bob*_*tle 13

首先是一个不忽略大小写的简单示例脚本:

#!/bin/bash
if [ $(echo hello) == hello ]; then
    echo it works
fi
Run Code Online (Sandbox Code Playgroud)

尝试更改右侧的字符串 hello ,它应该不再 echo it works。尝试用echo hello您选择的命令替换。如果您想忽略大小写,并且两个字符串都不包含换行符,那么您可以使用 grep:

#!/bin/bash
if echo Hello | grep -iqF hello; then
    echo it works
fi
Run Code Online (Sandbox Code Playgroud)

这里的关键是您将命令输出通过管道传输到grep. 该if语句测试管道中最右边命令的退出状态 - 在本例中为 grep。当且仅当找到匹配项时,Grep 才会成功退出。

-igrep的选项的说,忽略大小写。
-q选项表示在第一次匹配后不发出输出并退出。
-F选项表示将参数视为字符串而不是正则表达式。

请注意,第一个示例使用which 允许直接比较和各种有用的运算符。第二种形式只是执行命令并测试它们的退出状态。[ expression ]

  • 请注意,在实践中,这不仅仅是关于 Bourne shell。`==` 不是 POSIX。`sh` 不是所有基于 Linux 的系统上的 `bash`。`==` 不受 `ash`(至少许多 BSD 和 Debian 衍生产品的 `sh` 的基础)或 `posh` 支持,并且需要在 `zsh` 中引用。将 `=` 加倍是没有意义的。`[` 是用于测试的命令。这里没有必要在赋值和比较之间消除歧义。这在 `(( a == b ))` 和 `(( a = b))` 中是不同的。在以 `#! 开头的脚本中使用 `==` /bin/sh` 是错误的。如果您假设使用 `ksh` 或 `bash` 语法,请相应地更新 `#!`。 (2认同)

Gil*_*il' 8

对于区分大小写的字符串搜索变量的值的needle可变值haystack

case "$haystack" in
  *"$needle"*) echo "present";
  *) echo "absent";
esac
Run Code Online (Sandbox Code Playgroud)

对于不区分大小写的字符串搜索,将两者转换为相同的大小写。

uc_needle=$(printf %s "$needle" | tr '[:lower:]' '[:upper:]' ; echo .); uc_needle=${uc_needle%.}
uc_haystack=$(printf %s "$haystack" | tr '[:lower:]' '[:upper:]' ; echo .); uc_haystack=${uc_haystack%.}
case "$uc_haystack" in
  *"$uc_needle"*) echo "present";;
  *) echo "absent";;
esac
Run Code Online (Sandbox Code Playgroud)

请注意,trGNU coreutils 不支持多字节语言环境(例如 UTF-8)。要使用多字节语言环境,请改用 awk。如果您打算使用 awk,您可以让它进行字符串比较,而不仅仅是转换。

if awk 'BEGIN {exit !index(toupper(ARGV[2]), toupper(ARGV[1]))}' "$needle" "$haystack"; then
  echo "present"
else
  echo "absent"
fi
Run Code Online (Sandbox Code Playgroud)

tr从BusyBox的不支持的语法; 你可以改用。BusyBox 不支持非 ASCII 语言环境。[:CLASS:]tr a-z A-Z

在 bash(但不是 sh)4.0+ 版本中,有一个用于大小写转换的内置语法,以及一个用于字符串匹配的更简单的语法。

if [[ "${haystack^^}" = *"${needle^^}"* ]]; then
  echo "present"
else
  echo "absent"
esac
Run Code Online (Sandbox Code Playgroud)