如何编写一个 shell 脚本来执行命令输出的不区分大小写的子字符串匹配?
答案1
如果设置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
答案2
首先,这是一个不忽略大小写的简单示例脚本:
#!/bin/bash
if [ $(echo hello) == hello ]; then
echo it works
fi
尝试更改右侧的字符串 hello ,它应该不再 echo it works
。尝试echo hello
用您选择的命令替换。如果你想忽略大小写,并且两个字符串都不包含换行符,那么你可以使用 grep:
#!/bin/bash
if echo Hello | grep -iqF hello; then
echo it works
fi
这里的关键是您将命令输出通过管道传输到grep
.该if
语句测试管道中最右边命令的退出状态 - 在本例中为 grep。当且仅当 Grep 找到匹配项时才会成功退出。
grep 的选项-i
表示忽略大小写。
该-q
选项表示在第一次匹配后不发出输出并退出。
该-F
选项表示将参数视为字符串而不是正则表达式。
请注意,第一个示例使用了允许直接比较和各种有用的运算符。第二种形式只是执行命令并测试它们的退出状态。[ expression ]
答案3
needle
对于变量值中变量值的区分大小写的字符串搜索haystack
:
case "$haystack" in
*"$needle"*) echo "present";
*) echo "absent";
esac
对于不区分大小写的字符串搜索,请将两者转换为相同的大小写。
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
请注意,tr
GNU 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
BusyBoxtr
不支持该语法;你可以用它代替。 BusyBox 不支持非 ASCII 语言环境。[:CLASS:]
tr a-z A-Z
在 bash(但不是 sh)4.0+ 版本中,有一个用于大小写转换的内置语法,以及一个更简单的字符串匹配语法。
if [[ "${haystack^^}" = *"${needle^^}"* ]]; then
echo "present"
else
echo "absent"
esac