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


Answers:


72

如果你有重击

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"
  }
}'

32
对于使用if语句比较字符串的任何人,该shopt方法都要求您使用条件的双括号[[ ]]形式而不是单括号[ ]形式。另请参见: gnu.org/software/bash/manual/html_node/The-Shopt-Builtin.html
indiv 2012年

3
该问题表明它==用于比较两个字符串,但响应使用一条case语句演示了不区分大小写的比较。令人欣慰的是,该shopt解决方案还使得能够不区分大小写的使用===~和其它字符串比较操作符。
taranaki

7
shopt -u nocasematch比较完成后执行以恢复回bash的默认值可能是明智的。
Ohad Schneider

6
最好保存并还原nocasematch设置。抓住它,SHELLNOCASEMATCH=`shopt -p nocasematch`然后进行更改shopt -s nocasematch,一旦完成,请使用$SHELLNOCASEMATCH
Urhixidur

2
更好的是:SHELLNOCASEMATCH=$(shopt -p nocasematch; true),因为shopt -p如果未设置该选项,则会以代码1退出,如果有效,这可能导致脚本中止set -e
我们都是莫妮卡

158

在Bash中,您可以使用参数扩展将字符串修改为全部小写/大写:

var1=TesT
var2=tEst

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

14
至少是一个不包含购物选项的答复。因此,您可以比较两个忽略大小写的字符串,并在同一测试中将其他两个不区分大小写。谢谢
jehon 2014年

37
这是Bash 4中的新功能吗?至少在Bash 3.2.51(在OS X 10.9中使用)中不起作用-第一条echo语句导致:-bash: ${var1,,}: bad substitution
Felix Rabe 2014年

1
这种不区分大小写的比较实现容易出现本地化问题(例如土耳其语I问题)。我不知道该如何shopt -s nocasematch实现,但通常这种“语言级”解决方案可以正确处理它。
Ohad Schneider

5
@Ohad Schneider,让土耳其人担心土耳其的本地化问题,我只需要一种快速有效的字符串匹配方式,这将使蛋糕大大减少
niken

1
macOS用户,请升级您的Bash版本。到目前为止,您的文件已经过时了十年。itnext.io/upgradeing-bash-on-macos-7138bd1066ba
杰森·卡特

114

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

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

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


6
仅适用于Bash 4或更高版本(例如,不适用于Mac OS X 10.11)
d4Rk '16

8
@ d4Rk,这就是为什么我的回答的第一句话说“只要您有Bash 4”。话虽如此,在撰写此评论时,Bash 4已经发布了七年多了,而我自己的OS X安装已经将它花了很长时间了。
骚乱

@Riot很抱歉,首先没有注意到这一点。我知道您可以在OS X上安装任何所需的bash,但是默认值为3.2,并且由于我的脚本也必须在不同的Mac上运行,所以这对我来说不是一个选择。
d4Rk '16

2
@ d4Rk是可以理解的-如果您确实需要保证可移植性,我建议您坚持使用POSIX Shell标准,因为在某些情况下根本无法保证找到任何版本的bash。
骚乱

1
这正是我想要的。应该更高=)
Robin Winslow

39

保存nocasematch的状态(以防其他功能取决于它的禁用状态):

local orig_nocasematch=$(shopt -p nocasematch)
shopt -s nocasematch
[[ "foo" == "Foo" ]] && echo "match" || echo "notmatch"
$orig_nocasematch

注意:仅local在函数内部时使用。


4
很好,因为case陈述(包括在ghostdog回答中的陈述)将始终使我的皮肤爬行
SeldomNeedy 2015年

15

一种方法是将两个字符串都转换为大写或小写:

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

我用tr在我的搬运工-源化的应用程序基于高山(其提供方法sh通过busybox)。谢谢。
MXWest

7

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

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

2
就性能而言,这比启动awk或任何其他过程更好。
亚历克斯

1
在bash中,可以使用-l或-u声明来设置属性。
巴拉特

5

如果您使用fgrep进行不区分大小写的行比较,则非常简单:

str1="MATCH"
str2="match"

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

最好if fgrep -qix -- "$str1" <<<"$str2"; then改用。

3

这是我使用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

3

grep有一个-i标志,表示不区分大小写,因此请它告诉您var2是否在var1中。

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

3
如果var2中有任何正则表达式特殊字符,将无法正常工作。
haridsv

3

由于zsh语法略有不同,但仍比此处的大多数答案短:

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

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


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

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


1

我遇到了这个很棒的博客/教程/有关区分大小写模式的任何内容。通过示例详细解释以下三种方法:

1.使用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

3.开启nocasematch

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.