1463

如何在JavaScript中执行不区分大小写的字符串比较?

  • 44
    查看新添加的.localeCompare()javascript方法。在编写时仅受现代浏览器支持(IE11+)。看见developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 评论 2014年9月26日10:43
  • 8
    @阿德里安贝“A”.localeCompare(“A”);收益1在Chrome 48控制台中。 评论 2016年2月25日9:22
  • 1
    @曼努埃尔本地比较如果传递{敏感度:“重音”}{灵敏度:'base'}选项。“A”.localeCompare(“A”,未定义,{敏感度:“重音”})==0. 评论 2019年1月10日3:25

23答案23

重置为默认值
1529

编辑:这个答案最初是在10多年前添加的。今天应该使用localeCompare。请参阅其他答案。

最简单的方法(如果您不担心特殊的Unicode字符)是调用将字符串转换成大写:

var areEqual=字符串1.toUpperCase()===字符串2.toUpperCase();
10
  • 63
    转换为大写或小写确实可以在所有语言中提供正确的不区分大小写的比较。i18nguy.com/unicode/turkish-i18n.html 评论 2010年1月26日16:15
  • 68
    @山姆:我知道。所以我才写如果您不担心特殊的Unicode字符. 评论 2010年1月26日16:22
  • 201
    有理由选择吗将字符串转换成大写结束小写? 评论 2014年5月27日15:57
  • 179
  • 15
    @库格尔这个答案是9岁。从那时起,就有了新的功能,所以截至您发表评论之日,它并不是JS所能提供的最好的功能。请参阅下面的答案本地比较它是最近更新的(但仍然是五年前)。我不知道过去五年里发生了什么变化本地比较不再是最佳答案。 评论 2019年8月23日3:56
362

编辑:这个答案最初是9年前添加的。今天你应该使用本地比较使用敏感度:“重音”选项:

函数ci等于(a,b){返回typeof a===“字符串”&&typeof b===”string“? a.localeCompare(b,未定义,{敏感度:“重音”})===0:a===b;}console.log(“'a'='a'?”,ciEquals('a','a'));console.log(“AaaA'='AaA'?”,ciEquals(AaaA','aAAa'));console.log(“'a'='aa'?”,ciEquals('a','aa'));console.log(“'a'='b'?”,ciEquals('a','b'));

这个{敏感度:“重音”}告知本地比较()将相同基本字母的两个变体视为相同除非他们有不同的口音(如第三个例子所示)。

或者,您可以使用{灵敏度:“基本”},只要两个字符的基本字符相同(所以A类将被视为等同于á).

注释第三个参数本地比较IE10或更低版本或某些移动浏览器不支持(请参阅上面链接的页面上的兼容性图表),因此如果您需要支持这些浏览器,您将需要某种回退:

函数ciEqualsInner(a,b){return a.localeCompare(b,未定义,{sensitivity:“重音”})===0;}函数ci等于(a,b){if(typeof a!=='string'||typeof b!=='string'){返回a===b;}//v----特征检测return ciEqualsInner('A','A')? ci等于内部(a,b):/*此处采用后备方法*/;}

原始答案

在JavaScript中进行不区分大小写的比较的最佳方法是使用RegExp匹配()方法和标志。

不区分大小写的搜索

如果要比较的两个字符串都是变量(而不是常量),那么就比较复杂了,因为您需要从字符串生成RegExp,但如果字符串中包含特殊正则表达式字符,则将字符串传递给RegExp构造函数可能会导致不正确的匹配或失败的匹配。

如果你关心国际化,不要使用至下壳体()至UpperCase()因为它不能在所有语言中提供准确的区分大小写的比较。

http://www.i18nguy.com/unicode/turkish-i18n.html

8
  • 5
    @进退两难,是的,这就是我所说的必须处理的问题——“您需要从字符串生成RegExp,但如果字符串中包含特殊正则表达式字符,则将字符串传递给RegExp构造函数可能会导致不正确的匹配或失败的匹配” 评论 2014年6月6日17:29
  • 30
    使用这种方法进行区分大小写的字符串比较是成本最高的解决方案。RegExp用于复杂的模式匹配,因此,它需要为每个模式构建一个决策树,然后针对输入字符串执行该决策树。虽然它会起作用,但它相当于在下一个街区乘坐喷气式飞机去购物。tl;医生:请不要这样做。 评论 2015年4月1日11:30
  • 我可以使用localeCompare(),但它为返回-1'a'.localeCompare('a')和操作一样,我正在寻找不区分大小写的字符串比较。 评论 2018年3月19日1:53
  • 6
    @StingyJack要使用localeCompare进行区分大小写的比较,您应该执行“a”.localeCompare('a',undefined,{sensitivity:“base”}) 评论 2018年8月1日15:58
  • 2
    注:这个本地比较版本要求JavaScript引擎支持ECMAScript®国际化API,它是因此,在依赖它之前,您可能需要检查它是否在您使用的环境中工作。例如:constcompareInsensitive=“x”.localeCompare(“x”,未定义,{sensitive:“base”})===0?(a,b)=>a.localeCompare(b,未定义,{sensitivity:“base”}):(a,b)=>a.to LowerCase().localeCompare;或者一些类似的。 评论 2019年8月21日6:31
168

正如最近的评论所说,字符串::localeCompare支持不区分大小写的比较(除其他强大功能外)。

下面是一个简单的例子

“xyz”.localeCompare(“xyz”,未定义,{敏感度:“base”});//返回0

以及您可以使用的通用函数

函数等于IgnoringCase(文本,其他){return text.localeCompare(其他,未定义,{敏感度:'base'})===0;}

请注意未定义您可能应该输入正在使用的特定区域设置。如MDN文档中所述,这一点很重要

在瑞典语中,“ä”和“a”是分开的基本字母

灵敏度选项

MDN中列出的灵敏度选项

浏览器支持

发布时,UC浏览器适用于Android和Opera Mini不要支持区域设置选项参数。请检查https://caniuse.com/#search=localeCompare获取最新信息。

1
  • 1
    我很肯定浏览器不会定期去除对旧版本功能的支持,此处列出的浏览器支持不正确或至少不完整(根据您的caniuse链接)。IE<11、Firefox<29、Chrome<24和Safari<10(仅列出流行浏览器)也不支持区域设置选项参数,很可能在发布此答案时没有。对于新读者来说,这可能比列出的那些基本上不支持任何现代功能的晦涩浏览器有用得多。 评论 2020年11月4日23:42
55

更新:

根据评论,之前的答案检查源包含关键字,添加相等检查^$.

(/^关键字$/i).test(源代码)

借助正则表达式也可以实现。

(/keyword/i).test(源代码)

/我用于忽略大小写。如果没有必要,我们可以忽略并测试不区分大小写的匹配,如

(/keyword/).test(源代码)
4
  • 20
    使用这样的正则表达式将匹配子字符串!在您的示例中,字符串关键字将导致一场正面的比赛。但是绳子这是一个关键字yo关键字也将导致一场积极的比赛。请注意:-)
    – 埃尔默
    评论 2017年10月25日10:25
  • 7
    这不符合平等按照问题中的要求检查(不区分大小写)!但是,这是一个包含检查!不要用它 评论 2019年2月6日6:07
  • 7
    当然,为了匹配整个字符串,可以将regexp更改为/^关键字$/.test(源代码),但1)如果关键字不是一个常数,你需要这样做新RegExp(“^”+x+“$”).test(源代码)以及2)使用regexp来测试像区分大小写的字符串相等这样简单的东西根本不是很有效。
    – JHH公司
    评论 2019年5月10日8:08
  • const regexpEqual=(a,b)=>(新RegExp(^${a}(美元)$,“gi”)。测试(b) 评论 2023年3月29日9:40
35

请记住,大小写是特定于区域设置的操作。根据具体情况,您可能需要考虑这一点。例如,如果要比较两个人的姓名,可能需要考虑语言环境,但如果要比较机器生成的值(如UUID),则可能不需要考虑。这就是我在utils库中使用以下函数的原因(注意,出于性能原因,不包括类型检查)。

函数compareStrings(字符串1、字符串2、ignoreCase、useLocale){if(ignoreCase){if(useLocale){string1=字符串1.toLocaleLowerCase();string2=字符串2.toLocaleLowerCase();}其他{string1=字符串1.toLowerCase();string2=字符串2.toLowerCase();}}返回字符串1===字符串2;}
5
  • 1
    有没有理由使用“!!”来执行显式布尔转换,而不是允许if子句计算值的真实性?
    – 赛洛斯
    评论 2014年3月28日13:52
  • 这不是必须的。我想我是从其他版本的更复杂的代码中得到的。我已经更新了答案。 评论 2014年3月31日10:22
  • @你的函数有一个bug。这个比较字符串(“”,“”)将给予尽管字符串是相等的。
    – 塞尔格
    评论 2018年11月20日12:06
  • @谢尔盖这么做又回来了真的可能是你的浏览器有问题? 评论 2019年7月20日3:15
  • 地点无疑是一个需要考虑的重要因素+1
    – PHP专家
    评论 2020年9月7日7:18
14

如果您关心不等式的方向(也许您想对列表进行排序)您必须进行大小写转换,因为unicode中的小写字符比大写到lowercase的转换要多。

函数my_strcasecmp(a,b){if((a+'').toLowerCase()>(b+'')-toLowerCase())返回1if((a+'').toLowerCase()<(b+'')-toLowerCase())返回-1返回0}

Javascript似乎使用语言环境“C”进行字符串比较,因此结果排序将如果字符串包含ASCII字母以外的其他字母,则会很难看。如果不对字符串进行更详细的检查,就无法对此进行太多操作。

13

我最近创建了一个微型库,提供区分大小写的字符串帮助器:https://github.com/nickuratsev/ignore-case.(它使用将字符串转换成大写内部。)

var ignoreCase=要求('ignore-case');ignoreCase.equals('FOO','FOO');//=>真的ignoreCase.startsWith('foobar','FOO');//=>真的ignoreCase.endsWith('foobar','BaR');//=>真的ignoreCase.includes('AbCd','c');//=>真的ignoreCase.indexOf('AbCd','c');//=>2
0
8

使用RegEx进行字符串匹配或比较。

在JavaScript中,可以使用匹配()用于字符串比较,别忘了把在正则表达式中。此标志将强制进行不区分大小写的测试。

例子:

确认字符串测试任何情况下都包含在matchString(匹配字符串)变量

var matchString=“测试”;if(matchString.match(/test/i)){alert('matchString包含子字符串“test”不区分大小写');}其他{alert('matchString不包含子字符串“test”,不区分大小写');}

确认匹配字符串变量仅包含测试在任何情况下,如果没有其他字符,则使用零宽度断言^$在正则表达式中。这些将需要测试直接出现在字符串开头之后,并分别出现在字符串结尾之前。

var matchString=“测试”;if(matchString.match(/^test$/i)){alert('matchString等于“test”不区分大小写');}其他{alert('matchString不等于“test”不区分大小写');}
7
  • 确保您可以接受部分匹配,否则matchString.match(/^test$/i).
    – 哈克尔
    评论 2020年2月13日2:10
  • 用varx='test'代替小写的“test”是什么matchString.match(/x/i)工作?如果没有,什么会起作用? 评论 2020年5月5日18:03
  • @RazvanZamfir,在动态模式的情况下,您可以使用RegExp Object Ex:var x=new RegExp(/test/,“gi”);matchString.match(x); 评论 2021年3月26日14:58
  • 或者const x_regex=新RegExp(`^${x}$`,“gi”);尽管这很混乱。
    – 用户4945014
    评论 2021年10月15日2:13
  • 正则表达式性能不佳
    – 哔叽
    评论 2022年9月30日8:31
7

假设我们想找到字符串变量在字符串变量中干草堆有三个难题:

  1. 国际化应用程序应避免字符串到UpperCase字符串到下壳体。请使用忽略大小写的正则表达式。例如,var needRegExp=新RegExp(指针,“i”);然后针状膨胀试验(干草堆).
  2. 通常,您可能不知道.小心不包含任何正则表达式特殊字符。使用退出这些针.替换(/[-[\]{}()*+\\^$|#\s] /g,“\\$&”);.
  3. 在其他情况下,如果要精确匹配干草堆,忽略大小写,确保添加“^”一开始"$"在正则表达式构造函数的末尾。

考虑到第(1)点和第(2)点,示例如下:

var haystack=“A.BAIL.Of.Hay.”;var针=“bal.”;var needRegExp=新RegExp(指针.replace(/[-[\]{}()*+\\^$|#\s] /g,“\\$&”),“i”);var结果=needRegExp.test(干草堆);if(结果){//此处显示您的代码}
1
  • 当然!您只需更换新RegExp(…)第3行中包含以下内容:新RegExp(“^”+指针.replace(/[-[\]{}()*+\\^$|#\s] /g,“\\$&”)+“$”,“i”);。这可以确保搜索字符串前后没有其他字符. 评论 2016年7月26日21:23
7

这里有很多答案,但我想添加一个基于扩展String库的解决方案:

String.prototype.equalIgnoreCase=函数(str){return(str!=null&&typeof str===“字符串”&&this.toUpperCase()===str.toUpperCase());}

这样你就可以像在Java中一样使用它了!

例子:

var a=“hello”;var b=“HeLLo”;var c=“世界”;如果(a.equalIgnoreCase(b)){document.write(“a==b”);}如果(a.equalIgnoreCase(c)){document.write(“a==c”);}如果(!b.equalIgnoreCase(c)){document.write(“b!=c”);}

输出将是:

“a==b”“b!=c”

String.prototype.equalIgnoreCase=函数(str){return(str!=空&&typeof str===“字符串”&&this.toUpperCase()===字符串toUpperCase());}var a=“hello”;var b=“HeLLo”;var c=“世界”;如果(a.equalIgnoreCase(b)){document.write(“a==b”);document.write(“<br>”);}如果(a.equalIgnoreCase(c)){document.write(“a==c”);}如果(!b.equalIgnoreCase(c)){document.write(“b!=c”);}

1
  • 这是最清晰的解决方案,为您可能想要但语言中缺少的许多其他操作打开了大门。
    – 罗友美
    评论 2023年2月2日17:30
7

有两种方法可以进行不区分大小写的比较:

  1. 将字符串转换为大写,然后使用strict运算符进行比较(===).
  2. 使用字符串方法进行模式匹配:

使用“search”字符串方法进行不区分大小写的搜索。

<!doctype html><html><头部><脚本>//第1路var a=“苹果”;var b=“苹果”;如果(a.到UpperCase()===b.到Uppercase()){警报(“相等”);}//第2路var a=“Null and void”;document.write(a.search(/null/i));</script></头></html>

6

如果两个字符串的已知区域设置相同,则可能需要使用国际整理机对象如下:

函数equalIgnoreCase(s1:字符串,s2:字符串){return new Intl.Collator(“en-US”,{sensitivity:“base”}).compare(s1,s2)===0;}

显然,您可能需要缓存校对器以提高效率。

这种方法的优点是,它应该比使用RegExp快得多,并且基于一种非常可定制的区域设置选项上面文章中的构造函数参数)一组现成的collator。

1
  • 灵敏度的另一个选项是口音,使其不区分大小写,但会处理á作为单独的字符。所以基础口音根据具体需要,两者都是合适的。 评论 2018年4月13日16:28
5

我喜欢这个速记变体-

导出常量等于ignoreCase=(str1,str2)=>{return(!str1&&!str2)||(str1&&str2&&str1.toUpperCase()==str2.toUpperCase())}

处理速度快,并能实现预期目的。

我写了一个扩展。非常琐碎

if(类型String.prototype.isEqual!=“函数”){String.prototype.isEqual=函数(str){return this.toUpperCase()==str.toUpperCase();};}
  • 1
    对于String#isEqual应该如何工作,两个具有不同想法的代码基会发生什么? 评论 2013年9月20日22:15
  • @KhanSharp很多人认为修改内置类型的原型是反模式的。这就是为什么人们可能会对你的答案投反对票。 评论 2014年7月29日12:45
  • 1
    难道不应该优先考虑未知的方法定义吗?例如,一旦某些浏览器决定实施字符串#等于对象#等于从本质上讲,所有页面的行为都不同,如果规范与您的规范不完全匹配,可能会做出奇怪的事情。
    – 罗伯特
    评论 2014年12月8日0:07

甚至这个问题也已经得到了回答。我有一种不同的方法来使用RegExp和match来忽略大小写敏感性。请查看我的链接https://jsfiddle.net/marchdave/7v8bd7dq/27/

$(“#btnGuess”)。单击(guessWord);函数guessWord(){var letter=$(“#guessLetter”).val();var word=“ABC”;var pattern=RegExp(字母,'gi');//模式:/a/givar结果=word.match(模式);alert(“忽略大小写:”+result);}
2
str=“Lol”,str2=“Lol”,regex=新RegExp(“^”+str+“$”,“i”);if(regex.test(str)){console.log(“true”);}
0
2

将两者转换为较低的字符串(出于性能原因,只转换一次),并将其与内联三元运算符进行比较:

函数strcasecmp(s1,s2){s1=(s1+“”).到LowerCase();s2=(s2+'').toLowerCase();返回s1>s2?1:(s1<s2?-1:0);}
1
  • 1
    谁说C死了
    – 赛斯
    评论 2019年9月15日21:37
1

不抛出异常和不使用慢速正则表达式怎么样?

返回str1!=空&&str2!=无效的&&typeof str1===“string”&&typeof str2===”string“&&str1.toUpperCase()===str2.toUpperCase();

上面的代码段假设您不想匹配任何一个字符串为空或未定义的情况。

如果要匹配null/undefined,则:

return(str1==空&&str2==空)||(str1!=空&&str2!=空&&typeof str1===“string”&&typeof str2===”string“&&str1.toUpperCase()===str2.toUpperCase());

如果出于某种原因,您关心未定义与空:

return(str1===未定义&&str2===已定义)||(str1===空&&str2===零)||(str1!=null&&str2!=null&&typeof str1===“string”&&typeof str2===”string“&&str1.toUpperCase()===str2.toUpperCase());
1
  • 或者只是str1==str2||。。。 评论 2016年10月26日0:59
1

由于没有明确的答案,因此提供了一个简单的代码片段来使用注册Exp,这是我的尝试:

函数比较不敏感(str1,str2){str1的返回类型===“字符串”&&str2类型===“字符串”&&新RegExp(“^”+str1.replace(/[-\/\^$*+?.()|[\]{}]/g,'\\$&')+“$”,“i”).test(str2);}

它有几个优点:

  1. 验证参数类型(任何非字符串参数,如未定义例如,会使如下表达式崩溃str1.toUpperCase()).
  2. 不存在可能的国际化问题。
  3. 逃离注册Exp字符串。
2
1

如果你知道你正在处理ascii公司文本,然后您可以只使用大小写字符偏移量比较。

只需确保您的“完美”字符串(您要与之匹配的字符串)是小写的:

常量CHARS_IN_BETWEEN=32;常量LAST_UPPERCASE_CHAR=90;//Z轴函数strMatchesIgnoreCase(小写Match,value){设i=0,matches=lowercaseMatch.length===value.length;while(匹配&&i<小写Match.length){const a=小写Match.charCodeAt(i);常数A=A-CHARS_IN_BETWEEN;const b=value.charCodeAt(i);常数B=B+((B>LAST_UPPERCASE_CHAR)-CHARS_IN_BETWEEN:CHARS_IN-BETWEEN);匹配=a===b//更低a====b||A===b//上部A==b||a===B//更低a==~B||A===B;//上部A==~bi++;}返回匹配;}
1

为了更好地与浏览器兼容,您可以依赖正则表达式。这将适用于过去20年发布的所有web浏览器:

String.prototype.equalsci=函数{var regexp=regexp(“^”+this.replace(/[.\\+*?\[\^\]$(){}=!<>|:-]/g、 “\\$&”)+“$”,“i”);返回regexp.test;}“PERSON@ü.EXAMPLE.COM”.equalsci(“PERSON@ü/EXAMPLE.COM”)//返回true

这与这里的其他答案不同,因为它考虑到并非所有用户都在使用现代web浏览器。

注意:如果您需要支持不寻常的情况,如土耳其语,则需要使用localeCompare,因为我和我在土耳其文中不是同一个字母。

“I”.localeCompare(“I”,未定义,{sensitivity:“accent”})===0//返回true“I”.localeCompare(“I”,“tr”,{sensitivity:“accent”})===0//返回false
1
  • 最好使用Object.defineProperty来避免equalsci方法是可枚举的。
    – 用户4945014
    评论 2021年10月15日2:11
0

这是一个改进版属于这个答案.

String.equal=函数(s1,s2,ignoreCase,useLocale){if(s1==null || s2==null)返回false;if(!ignoreCase){如果(s1.length!==s2.length-)返回false;返回s1==s2;}if(useLocale){if(useLocale.length)return s1.toLocaleLowerCase(useLocale)===s2.toLocaleLoverCase(use Locale)其他的return s1.toLocaleLowerCase()===s2.toLocalLowerCasE()}其他{如果(s1.length!==s2.length-)返回false;返回s1.toLowerCase()===s2.到LowerCase[)];}}



使用和测试:

String.equal=函数(s1,s2,ignoreCase,useLocale){if(s1==null|s2==null)返回false;if(!ignoreCase){如果(s1.length!==s2.length-)返回false;返回s1==s2;}if(useLocale){if(useLocale.length)return s1.toLocaleLowerCase(useLocale)===s2.toLocaleLoverCase(use Locale)其他的return s1.toLocaleLowerCase()===s2.toLocalLowerCasE()}其他{如果(s1.length!==s2.length-)返回false;返回s1.toLowerCase()===s2.到LowerCase[)];}}//如果您不介意扩展原型。String.prototype.equal=函数(string2,ignoreCase,useLocale){return String.equal(this.valueOf(),string2,ignoreCase,useLocale);}//------------------测试----------------------console.log(“测试…”);console.log('区分大小写1');var result=“Abc123”.equal(“Abc123”);console.assert(结果===true);console.log('区分大小写2');result=“aBC123”.equal(“aBC123”);console.assert(结果===false);console.log(“忽略情况”);result=“AbC123”.equal(“AbC123”,true);console.assert(结果===true);console.log('忽略大小写+当前区域设置');result=“AbC123”.equal(“AbC123”,true);console.assert(结果===true);console.log(“土耳其测试1(忽略案例,en-US)”);result=“IiI”.equal(“i i i”,true,“en-US”);console.assert(结果===false);console.log(“土耳其测试2(忽略案例,tr-tr)”);result=“IiI”.equal(“i i i”,true,“tr-tr”);console.assert(结果===true);console.log(“土耳其测试3(区分大小写,tr-tr)”);result=“IiI”.equal(“i i”,false,“tr-tr”);console.assert(结果===false);控制台.log('null-test-1');result=“AAA”.equal(null);console.assert(结果===false);控制台.log('null-test-2');result=String.equal(null,“BBB”);console.assert(结果===false);控制台.log('null-test-3');result=String.equal(null,null);console.assert(结果===false);

0

我们也可以使用ASCII:

降低功能(a){设c=“”;for(设i=0;i<a.length;i++){设f=a.charCodeAt(i);如果(f<95){c+=字符串.fromCharCode(f+32);}其他{c+=a[i];}}返回c;}功能比较(a,b){返回到下限(a)==到下限(b);}console.log(compareIt(“An ExamPlE”,“An ExamPlE”));

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.