Shell 脚本中字符串的不区分大小写比较

==操作符用于比较 shell 脚本中的两个字符串。但是,我想比较两个字符串忽略的情况下,如何可以做到这一点?有什么标准指令吗?

259314 次浏览

商店没有办公室

一种方法是将两个字符串都转换为上或下:

test $(echo "string" | /bin/tr '[:upper:]' '[:lower:]') = $(echo "String" | /bin/tr '[:upper:]' '[:lower:]') && echo same || echo different

另一种方法是使用 grep:

echo "string" | grep -qi '^String$' && echo same || echo different

如果你有 Bash 的话

str1="MATCH"
str2="match"
shopt -s nocasematch
case "$str1" in
$str2 ) echo "match";;
*) echo "no match";;
esac

否则,您应该告诉我们您使用的是什么 shell。

选择,使用 awk

str1="MATCH"
str2="match"
awk -vs1="$str1" -vs2="$str2" 'BEGIN {
if ( tolower(s1) == tolower(s2) ){
print "match"
}
}'

grep有一个 -i标志,这意味着不区分大小写,因此要求它告诉您 var2是否在 var1中。

var1=match
var2=MATCH
if echo $var1 | grep -i "^${var2}$" > /dev/null ; then
echo "MATCH"
fi

保存 nocasematch的状态(以防其他函数依赖于它被禁用) :

local orig_nocasematch=$(shopt -p nocasematch; true)
shopt -s nocasematch


[[ "foo" == "Foo" ]] && echo "match" || echo "notmatch"


$orig_nocasematch

注意: local仅在函数内部需要。
此外,当 set -e打开且 $(shopt -p nocasematch)失败时,; true部分将防止 shell 退出(因为根本没有设置 nocasematch)。

对于 korn shell,我使用排版内置命令(- l 表示小写,-u 表示大写)。

var=True
typeset -l var
if [[ $var == "true" ]]; then
print "match"
fi

在 Bash 中,可以使用参数展开将字符串修改为所有大小写:

var1=TesT
var2=tEst


echo ${var1,,} ${var2,,}
echo ${var1^^} ${var2^^}

所有这些答案都忽略了最简单、最快捷的方法(只要你有 Bash 4) :

if [ "${var1,,}" = "${var2,,}" ]; then
echo ":)"
fi

您所要做的就是将两个字符串都转换为小写并比较结果。

下面是我使用 tr 的解决方案:

var1=match
var2=MATCH
var1=`echo $var1 | tr '[A-Z]' '[a-z]'`
var2=`echo $var2 | tr '[A-Z]' '[a-z]'`
if [ "$var1" = "$var2" ] ; then
echo "MATCH"
fi

如果使用 fgrep 进行不区分大小写的行比较,那么非常容易:

str1="MATCH"
str2="match"


if [[ $(fgrep -ix $str1 <<< $str2) ]]; then
echo "case-insensitive match";
fi

对于 zsh,语法稍有不同,但仍然比这里的大多数答案要短:

> str1='mAtCh'
> str2='MaTcH'
> [[ "$str1:u" = "$str2:u" ]] && echo 'Strings Match!'
Strings Match!
>

这将在比较之前将两个字符串都转换为大写。


另一种方法使用 zsh 的 globbing flags,它允许我们通过使用 i globb 标志直接使用不区分大小写的匹配:

setopt extendedglob
[[ $str1 = (#i)$str2 ]] && echo "Match success"


# this example compares the variable with a literal string 'match'
[[ $str1 = (#i)match ]] && echo "Match success"

我偶然发现了这个很棒的关于 处理区分大小写的模式的博客/教程/任何东西:

使用 Tr命令将模式转换为小写

opt=$( tr '[:upper:]' '[:lower:]' <<<"$1" )
case $opt in
sql)
echo "Running mysql backup using mysqldump tool..."
;;
sync)
echo "Running backup using rsync tool..."
;;
tar)
echo "Running tape backup using tar tool..."
;;
*)
echo "Other options"
;;
esac

2. 小心使用大小写模式

opt=$1
case $opt in
[Ss][Qq][Ll])
echo "Running mysql backup using mysqldump tool..."
;;
[Ss][Yy][Nn][Cc])
echo "Running backup using rsync tool..."
;;
[Tt][Aa][Rr])
echo "Running tape backup using tar tool..."
;;
*)
echo "Other option"
;;
esac

打开

opt=$1
shopt -s nocasematch
case $opt in
sql)
echo "Running mysql backup using mysqldump tool..."
;;
sync)
echo "Running backup using rsync tool..."
;;
tar)
echo "Running tape backup using tar tool..."
;;
*)
echo "Other option"
;;
esac


shopt -u nocasematch

‘ tr’实用程序(翻译字符)总是出现在所有 Unix/Linux 机器上,并且是轻量级的。

下面是一个函数,可用于处理不区分大小写的比较。由于‘ tr’的确切位置可能不同,因此我们首先探测它可能的位置,并将正确的位置存储在一个名为“ BIN _ TR”的 env 变量中。

declare BIN_TR=$( ls /bin/tr /usr/bin/tr 2>/dev/null | head -1 );

然后在函数声明中使用。

toLowerCase() {
echo "$*" | $BIN_TR '[:upper:]' '[:lower:]'
}

使用“ tr”的解决方案可望在不同的操作系统和操作系统设置之间具有高度可移植性。虽然‘ awk’也是非常可能的,但是与‘ awk’相比,‘ tr’实用程序很小,因此使用‘ tr’的函数可能更轻量级。

在类 Unix 操作系统上,test 命令检查文件类型并比较值。

str1="MATCH"
str2="match"


if test $str1 =  $str2
then
echo "equal yes"
else
echo "equal not"
fi

在类 Unix 操作系统上,test 命令检查文件类型并比较值。

很简单。

在几行代码中