如何在JavaScript中执行不区分大小写的字符串比较?
编辑:此答案最初是在10年前添加的。今天应该使用localeCompare。请参见其他答案。
如果您不担心特殊的Unicode字符,最简单的方法是调用toUpperCase
:
var areEqual = string1.toUpperCase() === string2.toUpperCase();
toLowerCase
,有理由更喜欢使用 toUpperCase
吗? - jpmc26localeCompare
的更新更近的答案(但仍然是5年前)。我不知道过去五年里是否有任何变化使 localeCompare
不再是最好的答案。 - Samuel Neff编辑:这个回答最初是在9年前添加的。今天您应该使用localeCompare
与sensitivity: 'accent'
选项:
function ciEquals(a, b) {
return typeof a === 'string' && typeof b === 'string'
? a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0
: a === b;
}
console.log("'a' = 'a'?", ciEquals('a', 'a'));
console.log("'AaA' = 'aAa'?", ciEquals('AaA', 'aAa'));
console.log("'a' = 'á'?", ciEquals('a', 'á'));
console.log("'a' = 'b'?", ciEquals('a', 'b'));
{ sensitivity: 'accent' }
会告诉localeCompare()
将同一基本字母的两个变体视为相同,除非它们具有不同的重音(如上面的第三个示例)。
或者,您可以使用{ sensitivity: 'base' }
,只要它们的基本字符相同,就将两个字符视为等效(因此A
将被视为等效于á
)。
请注意,localeCompare
的第三个参数不受IE10或更低版本或某些移动浏览器的支持(请参见上面链接页面上的兼容性图表),因此如果您需要支持这些浏览器,您需要一些备用方案:
function ciEqualsInner(a, b) {
return a.localeCompare(b, undefined, { sensitivity: 'accent' }) === 0;
}
function ciEquals(a, b) {
if (typeof a !== 'string' || typeof b !== 'string') {
return a === b;
}
// v--- feature detection
return ciEqualsInner('A', 'a')
? ciEqualsInner(a, b)
: /* fallback approach here */;
}
原始答案
在JavaScript中执行不区分大小写的比较的最佳方法是使用RegExp match()
方法及i
标志。
当被比较的两个字符串都是变量(而非常量)时,就有点棘手了,因为你需要从字符串生成一个RegExp,但是将字符串传递给RegExp构造函数可能导致不正确的匹配或匹配失败,如果字符串中包含特殊的正则表达式字符。
如果您关心国际化,请勿使用toLowerCase()
或toUpperCase()
,因为它无法提供所有语言的准确的不区分大小写比较。
localeCompare
版本要求 JavaScript 引擎支持 ECMAScript® 国际化 API,但这并非必须。因此,在依赖它之前,您可能需要检查它在您使用的环境中是否可用。例如:const compareInsensitive = "x".localeCompare("X", undefined, {sensitivity: "base"}) === 0 ? (a, b) => a.localeCompare(b, undefined, {sensitivity: "base"}) : (a, b) => a.toLowerCase().localeCompare(b.toLowerCase());
或类似的内容。 - T.J. Crowder如最近的评论所说,string::localeCompare
支持大小写不敏感比较(以及其他强大的功能)。
这是一个简单的例子:
'xyz'.localeCompare('XyZ', undefined, { sensitivity: 'base' }); // returns 0
还有一个通用的函数可以使用
function equalsIgnoringCase(text, other) {
return text.localeCompare(other, undefined, { sensitivity: 'base' }) === 0;
}
请注意,不要使用undefined
,而应该输入您正在使用的具体语言环境。正如MDN文档所示,这非常重要。
在瑞典语中,ä和a是单独的基本字母。
截至发布时,安卓UC浏览器和Opera Mini不支持locale和options参数。请查看https://caniuse.com/#search=localeCompare以获取最新信息。
根据评论,之前的答案检查了source包含关键字
,为了进行等值检查,添加了^
和$
。
(/^keyword$/i).test(source)
借助正则表达式,我们也可以实现。
(/keyword/i).test(source)
/i
是忽略大小写的。如果不需要,我们可以忽略并测试不区分大小写的匹配方式,如:
(/keyword/).test(source)
keyWORD
将确实导致正匹配。但是字符串 this is a keyword yo
或 keywords
也将导致正匹配。请注意 :) - Elmer/^keyword$/.test(source)
,但是,1)如果keyword
不是一个恒定的值,你需要执行 new RegExp('^' + x +'$')。test(source)
;2)使用正则表达式来测试如此简单的不区分大小写的字符串相等性并不高效。 - JHH^${a}$
, "gi")).test(b) - Sam Hasler请记住,大小写转换是与语言环境相关的操作。根据情况,您可能需要考虑这一点。例如,如果您要比较两个人的姓名,则可能要考虑语言环境,但如果您要比较机器生成的值,例如UUID,则可能不需要。这就是为什么我在我的实用程序库中使用以下函数(注意,出于性能原因,未包含类型检查)。
function compareStrings (string1, string2, ignoreCase, useLocale) {
if (ignoreCase) {
if (useLocale) {
string1 = string1.toLocaleLowerCase();
string2 = string2.toLocaleLowerCase();
}
else {
string1 = string1.toLowerCase();
string2 = string2.toLowerCase();
}
}
return string1 === string2;
}
compareStrings("", "")
会返回false
,尽管这两个字符串是相等的。 - Sergfunction my_strcasecmp( a, b )
{
if((a+'').toLowerCase() > (b+'').toLowerCase()) return 1
if((a+'').toLowerCase() < (b+'').toLowerCase()) return -1
return 0
}
Javascript似乎在字符串比较时使用地区设置"C",因此如果字符串中包含除ASCII字母以外的内容,则结果排序将变得不美观。除非对字符串进行更详细的检查,否则不太可能解决这个问题。
我最近创建了一个微型库,提供了不区分大小写的字符串助手:https://github.com/nickuraltsev/ignore-case。(它在内部使用toUpperCase
。)
var ignoreCase = require('ignore-case');
ignoreCase.equals('FOO', 'Foo'); // => true
ignoreCase.startsWith('foobar', 'FOO'); // => true
ignoreCase.endsWith('foobar', 'BaR'); // => true
ignoreCase.includes('AbCd', 'c'); // => true
ignoreCase.indexOf('AbCd', 'c'); // => 2
使用正则表达式进行字符串匹配或比较。
在JavaScript中,您可以使用match()
进行字符串比较,
不要忘记在正则表达式中加上i
。此标志将强制执行不区分大小写的测试。
示例:
确认任何情况下的字符串test
是否包含在matchString
变量的任何位置中
var matchString = "Test";
if (matchString.match(/test/i)) {
alert('matchString contains the substring "test" case insensitive');
}
else {
alert('matchString does not contain the substring "test" case insensitive');
}
要确认matchString
变量只包含任何大小写的test
,且没有其他字符,则使用正则表达式中的零宽断言^
和$
。这些将要求test
直接出现在字符串开头之后和字符串结尾之前。
var matchString = "Test";
if (matchString.match(/^test$/i)) {
alert('matchString equals "test" case insensitive');
}
else {
alert('matchString does not equal "test" case insensitive');
}
matchString.match(/^test$/i)
。 - hackelvar x = 'test'
,那么 matchString.match(/x/i)
能起作用吗?如果不能,应该如何操作? - Razvan Zamfirconst x_regex = new RegExp(`^${x}$`, "gi");
,不过有点乱。 - user4945014String.prototype.equalIgnoreCase = function(str)
{
return (str != null
&& typeof str === 'string'
&& this.toUpperCase() === str.toUpperCase());
}
这样你就可以像在Java中一样使用它了!
例如:
var a = "hello";
var b = "HeLLo";
var c = "world";
if (a.equalIgnoreCase(b)) {
document.write("a == b");
}
if (a.equalIgnoreCase(c)) {
document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
document.write("b != c");
}
"a == b"
"b != c"
String.prototype.equalIgnoreCase = function(str) {
return (str != null &&
typeof str === 'string' &&
this.toUpperCase() === str.toUpperCase());
}
var a = "hello";
var b = "HeLLo";
var c = "world";
if (a.equalIgnoreCase(b)) {
document.write("a == b");
document.write("<br>");
}
if (a.equalIgnoreCase(c)) {
document.write("a == c");
}
if (!b.equalIgnoreCase(c)) {
document.write("b != c");
}
haystack 中查找字符串变量 needle 。 有三个需要注意的地方:
- 国际化应用程序应避免使用
string.toUpperCase
和 string.toLowerCase
。改为使用忽略大小写的正则表达式。例如,var needleRegExp = new RegExp(needle, "i");
后跟 needleRegExp.test(haystack)
。
- 通常情况下,您可能不知道
needle
的值。请注意,needle
不包含任何正则表达式 特殊字符。可以使用 needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
进行转义。
- 在其他情况下,如果您想精确匹配
needle
和 haystack
,只需忽略大小写,请确保在您的正则表达式构造函数开头添加 "^"
,并在结尾添加 "$"
。
考虑到上述要点(1)和(2),一个示例如下:
var haystack = "A. BAIL. Of. Hay.";
var needle = "bail.";
var needleRegExp = new RegExp(needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), "i");
var result = needleRegExp.test(haystack);
if (result) {
// Your code here
}
new RegExp(...)
部分替换为以下内容:new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");
。这样可以确保在你的搜索字符串needle
之前或之后没有其他字符。 - Chris Chute
.localeCompare()
JavaScript 方法。目前仅有现代浏览器支持(IE11+)。请参阅 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare 。 - Adriano"A".localeCompare( "a" )
返回值为1。 - manuell{ sensitivity: 'accent' }
或{ sensitivity: 'base' }
选项,则localeCompare
将执行不区分大小写的比较。"A".localeCompare("a", undefined, { sensitivity: 'accent' }) === 0
。 - JLRishe