대소 문자를 구분하지 않는 문자열 비교를 수행하는 방법은 무엇입니까?


1056

JavaScript에서 대소 문자를 구분하지 않는 문자열 비교는 어떻게 수행합니까?


25
새로 추가 된 .localeCompare()자바 스크립트 메소드를 참조하십시오 . 작성 당시 최신 브라우저에서만 지원됩니다 (IE11 +). developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Adrien Be


5
@AdrienBe "A".localeCompare( "a" );1Chrome 48 콘솔로 돌아갑니다 .
manuell

3
@manuell "a""A"정렬 할 때 앞에 오는 것을 의미 합니다. 처럼 "a"전에 온다 "b". 이 동작을 원하지 않으면 .toLowerCase()각 문자 / 문자열을 원할 수 있습니다 . 즉. "A".toLowerCase().localeCompare( "a".toLowerCase() )참조 developer.mozilla.org/en/docs/Web/JavaScript/Reference/...
아드는 수

2
비교는 종종 문자열 정렬 / 순서 지정에 사용되는 용어이기 때문에. 나는 오래 전에 여기에 댓글을 달았습니다. ===평등을 검사하지만 문자열을 정렬 / 순서 지정하기에는 충분하지 않습니다 (참조, 원래 링크 된 질문).
Adrien Be

답변:


1162

특별한 유니 코드 문자에 대해 걱정하지 않는 경우 가장 간단한 방법은 다음을 호출하는 것입니다 toUpperCase.

var areEqual = string1.toUpperCase() === string2.toUpperCase();

44
대소 문자를 변환하면 모든 언어에서 대소 문자를 구분하지 않는 정확한 비교를 제공합니다. i18nguy.com/unicode/turkish-i18n.html
사무엘 네프

57
@sam : 알아요. 내가 쓴 이유 if you're not worried about special Unicode characters입니다.
SLaks

141
선호하는 이유가 toUpperCase이상은 toLowerCase?
jpmc26


19
이것이 정말로 JS가 제공하는 최고의 것입니까?
Kugel

210

편집 :이 답변은 원래 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처리 á).

참고 그 세 번째 매개 변수 localeCompareIE10에서 지원 또는 낮추거나 당신이 그 브라우저를 지원해야하는 경우, 당신은 대체 어떤 종류의가 필요합니다 그래서 특정 모바일 브라우저 (위에 링크 된 페이지의 호환성 차트를 참조)되지 않습니다

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에서 대소 문자를 구분하지 않는 비교를 수행하는 가장 좋은 방법 match()i플래그 와 함께 RegExp 메소드 를 사용 하는 것 입니다.

대소 문자를 구분하지 않는 검색

비교되는 두 문자열이 모두 상수가 아닌 변수 인 경우 문자열에서 RegExp를 생성해야하지만 RegExp 생성자에 문자열을 전달하면 문자열에 특수 정규 표현식이있는 경우 일치하지 않거나 일치하지 않을 수 있으므로 조금 더 복잡합니다. 그 안에 문자.

당신이 국제화에 대해 관심이있는 경우 사용하지 않습니다 toLowerCase()또는 toUpperCase()이 모든 언어의 정확한 대소 문자를 구분 비교를 제공하지 않는 한.

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


5
@Quandary, 예, 내가 처리해야한다고 말한 것입니다. "문자열에서 RegExp를 생성해야하지만 문자열을 RegExp 생성자에 전달하면 문자열에 특수한 정규식 문자가 있으면 일치하지 않거나 일치하지 않을 수 있습니다."
사무엘 네프

21
대소 문자를 구분하지 않는 문자열 비교를 위해 가장 비용이 많이 드는 솔루션입니다. RegExp는 복잡한 패턴 일치를위한 것이므로 각 패턴에 대해 의사 결정 트리를 작성한 다음 입력 문자열에 대해이를 실행해야합니다. 그것은 작동하지만 제트 비행기를 타고 다음 블록에서 쇼핑을하는 것과 비교할 수 있습니다. tl; dr : 이러지 마십시오.
Agoston Horvath

2
localeCompare ()를 사용할 수는 있지만 'a'.localeCompare('A')대소 문자를 구분하지 않는 문자열 비교를 찾고있는 op에 대해 -1을 반환 합니다.
StingyJack

3
'('정의되지 않은, {감도를 '베이스'})는 a'.localeCompare '를해야한다, 대소 문자 구분이 localeCompare를 사용하여 비교할 할 @StingyJack
유다 가브리엘 희망 고

1
참고 :localeCompare버전을 사용하려면 JavaScript 엔진이 ECMAScript® Internationalization 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());과 같습니다.
TJ Crowder

46

최근 의견에서 언급했듯이 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는 별도의 기본 문자입니다.

감도 옵션

MDN에서 표식 된 감도 옵션

브라우저 지원

게시 시점 현재 Android 용 UC 브라우저 및 Opera Mini 로캘옵션 매개 변수를 지원 하지 않습니다 . 최신 정보는 https://caniuse.com/#search=locale 비교 를 확인 하십시오 .


35

정규 표현의 도움으로 우리도 달성 할 수 있습니다.

(/keyword/i).test(source)

/i무시하는 경우입니다. 필요하지 않은 경우와 같이 대소 문자를 구분하지 않는 NOT을 무시하고 테스트 할 수 있습니다

(/keyword/).test(source)

17
이와 같은 정규 표현식을 사용하면 하위 문자열과 일치합니다! 귀하의 예에서 문자열 keyWORD은 죽지 않아 긍정적으로 일치합니다. 그러나 문자열 this is a keyword yo또는 keywords긍정적 인 결과를 가져올 것입니다. :-)
Elmer

6
질문에서 요청한대로 평등 검사 (대소 문자 구분)에 응답하지 않습니다 ! 그러나 이것은 포함 확인입니다! 사용하지 마십시오
S.Serpooshan

4
물론 전체 문자열을 일치시키기 위해 정규 표현식을로 변경할 수 /^keyword$/.test(source)있지만 1) keyword상수가 아닌 경우 new RegExp('^' + x + '$').test(source)2) 대소 문자를 구분하지 않는 문자열 동등성만큼 간단한 것을 테스트하기 위해 정규 표현식을 사용해야합니다. 전혀 효율적이지 않습니다.
JHH

28

케이싱은 로캘 별 작업입니다. 시나리오에 따라 고려해야 할 수도 있습니다. 예를 들어, 두 사람의 이름을 비교하는 경우 로케일을 고려할 수 있지만 UUID와 같은 기계 생성 값을 비교하는 경우 그렇지 않을 수 있습니다. 이것이 내가 utils 라이브러리에서 다음 기능을 사용하는 이유입니다 (성능상의 이유로 유형 검사는 포함되지 않음).

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;
}

"!!"를 사용하는 이유가 있습니까? if 절이 값의 진실성을 평가하도록 허용하는 대신 명시 적 부울 변환을 수행합니까?
Celos

필요하지 않습니다. 다른 버전의 더 복잡한 코드에서 얻은 것 같습니다. 답변을 업데이트했습니다.
Shital Shah

@thekodester 함수에 버그가 있습니다. 이것은 compareStrings("", "")줄 것이다 false에도 불구하고 문자열이 동일한 사실을.
Sergey

@Sergey 그게 true나에게 돌아온다 . 아마도 그것은 브라우저의 버그입니까?
Jenna Sloan

14

: 나는 최근에 대소 문자를 구분 문자열 도우미를 제공하는 마이크로 라이브러리 생성 한 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

12

불평등의 방향에 대해 우려하는 경우 (아마 목록을 정렬하려는 경우) 대소 문자 변환을 수행해야하며 유니 코드에는 대문자보다 소문자가 많으므로 toLowerCase는 아마도 가장 좋은 변환입니다.

function my_strcasecmp( a, b ) 
{
    if((a+'').toLowerCase() > (b+'').toLowerCase()) return 1  
    if((a+'').toLowerCase() < (b+'').toLowerCase()) return -1
    return 0
}

Javascript는 문자열 비교에 로케일 "C"를 사용하는 것으로 보이므로 문자열에 ASCII 문자 이외의 문자가 포함되어 있으면 결과 순서가 추악합니다. 줄을 훨씬 더 자세히 검사하지 않고는 할 수있는 일이 많지 않습니다.


7

문자열 변수 needle에서 문자열 변수를 찾고 싶다고 가정 합니다 haystack. 세 가지 문제가 있습니다.

  1. 국제화 된 응용 프로그램은 string.toUpperCase및 을 피해야 string.toLowerCase합니다. 대신 대소 문자를 무시하는 정규식을 사용하십시오. 예를 들어, var needleRegExp = new RegExp(needle, "i");뒤에 needleRegExp.test(haystack).
  2. 일반적으로의 값을 모를 수 있습니다 needle. needle정규 표현식 특수 문자를 포함하지 않도록주의하십시오 . 를 사용하여 이스케이프 처리하십시오 needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");.
  3. 다른 경우에는, 경우에 정확하게 일치시킬 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(...)3 행 의 부품 을 다음으로 교체하기 만하면됩니다 new RegExp("^" + needle.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&") + "$", "i");.. 이렇게하면 검색 문자열 앞뒤에 다른 문자가 없어야합니다 needle.
Chris Chute

4

대소 문자를 구분하지 않는 비교에는 두 가지 방법이 있습니다.

  1. 문자열을 대문자로 변환 한 다음 엄격한 연산자 ( ===)를 사용하여 비교하십시오 . 엄격한 연산자가 피연산자를 읽는 방법 읽기 자료 : http://www.thesstech.com/javascript/relational-logical-operators
  2. 문자열 메소드를 사용한 패턴 일치 :

대소 문자를 구분하지 않는 검색에는 "search"문자열 방법을 사용하십시오. http://www.thesstech.com/pattern-matching-using-string-methods 에서 검색 및 기타 문자열 메소드에 대해 읽으십시오 .

<!doctype html>
  <html>
    <head>
      <script>

        // 1st way

        var a = "apple";
        var b = "APPLE";  
        if (a.toUpperCase() === b.toUpperCase()) {
          alert("equal");
        }

        //2nd way

        var a = " Null and void";
        document.write(a.search(/null/i)); 

      </script>
    </head>
</html>

4

여기에 많은 답변이 있지만 String lib 확장을 기반으로 솔루션을 추가하고 싶습니다.

String.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");
}


4

문자열 일치 또는 비교에 RegEx를 사용하십시오.

JavaScript에서는 match()문자열 비교에 사용할 수 있습니다 i. RegEx를 반드시 입력하십시오.

예:

var matchString = "Test";
if (matchString.match(/test/i)) {
  alert('String matched');
}
else {
 alert('String not matched');
}

1
부분적으로 일치하는지 확인하십시오 matchString.match(/^test$/i). 그렇지 않으면 .
hackel

소문자 "test"대신 var x = 'test'가 matchString.match(/x/i)있습니까? 그렇지 않은 경우 어떻게 작동합니까?
Razvan Zamfir

3
str = 'Lol', str2 = 'lOl', regex = new RegExp('^' + str + '$', 'i');
if (regex.test(str)) {
    console.log("true");
}

3

두 문자열이 모두 알려진 로케일 인 경우 다음 Intl.Collator과 같은 객체 를 사용할 수 있습니다 .

function equalIgnoreCase(s1: string, s2: string) {
    return new Intl.Collator("en-US", { sensitivity: "base" }).compare(s1, s2) === 0;
}

Collator더 나은 효율성 을 위해 캐시를 저장하는 것이 좋습니다.

이 접근 방식의 장점은 RegExps를 사용하는 것보다 훨씬 빠르며 바로 사용할 수있는 collator 세트를 매우 사용자 정의 할 수 있다는 것입니다 ( 위 기사의 설명 localesoptions생성자 매개 변수 설명 참조 ).


감도 또 다른 옵션은 accent그 사례를 구분을 유지하지만 취급하는, a그리고 á별도의 문자로. 그래서 baseaccent모두 정확한 필요에 따라 적절한 수 있습니다.
Matthew Crumley

2

나는 확장을 썼다. 매우 사소한

if (typeof String.prototype.isEqual!= 'function') {
    String.prototype.isEqual = function (str){
        return this.toUpperCase()==str.toUpperCase();
     };
}

1
String # isEqual의 작동 방식에 대한 아이디어가 다른 두 개의 코드베이스가 동시에 존재하려면 어떻게됩니까?
Ryan Cavanaugh

3
@KhanSharp 많은 사람들이 내장 유형의 프로토 타입을 수정하기 위해 반 패턴이라고 생각합니다. 이것이 사람들이 귀하의 답변을 거절하는 이유입니다.
jt000

1
알려지지 않은 분석법 정의를 선호하는 것은 좋지 않습니까? 예를 들어 일부 브라우저가 구현을 결정 String#isEqual하거나 Object#isEqual기본적으로 모든 페이지가 다르게 작동하고 사양이 정확하게 일치하지 않으면 이상한 일을 할 수 있습니다.
Robert

2

이 질문조차도 이미 대답했습니다. 대소 문자 구분을 무시하기 위해 RegExp 및 match를 사용하는 다른 방법이 있습니다. 내 링크 https://jsfiddle.net/marchdave/7v8bd7dq/27/를 참조하십시오

$("#btnGuess").click(guessWord);

  function guessWord() {

   var letter = $("#guessLetter").val();
   var word = 'ABC';
   var pattern = RegExp(letter, 'gi'); // pattern: /a/gi

   var result = word.match(pattern);
   alert('Ignore case sensitive:' + result);

  }

1

예외를 던지거나 느린 정규 표현식을 사용하지 않는 것은 어떻습니까?

return str1 != null && str2 != null 
    && typeof str1 === 'string' && typeof str2 === 'string'
    && str1.toUpperCase() === str2.toUpperCase();

위의 스 니펫은 문자열이 null이거나 정의되지 않은 경우 일치하지 않는다고 가정합니다.

null / undefined와 일치 시키려면 다음을 수행하십시오.

return (str1 == null && str2 == null)
    || (str1 != null && str2 != null 
        && typeof str1 === 'string' && typeof str2 === 'string'
        && str1.toUpperCase() === str2.toUpperCase());

어떤 이유로 undefined vs null이 걱정되는 경우 :

return (str1 === undefined && str2 === undefined)
    || (str1 === null && str2 === null)
    || (str1 != null && str2 != null 
        && typeof str1 === 'string' && typeof str2 === 'string'
        && str1.toUpperCase() === str2.toUpperCase());

아니면 그냥str1 == str2 || ...
SLaks

1

에 대한 간단한 코드 스 니펫을 명확하게 제공 한 답변이 없으므로 RegExp여기 내 시도가 있습니다.

function compareInsensitive(str1, str2){ 
  return typeof str1 === 'string' && 
    typeof str2 === 'string' && 
    new RegExp("^" + str1.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + "$", "i").test(str2);
}

몇 가지 장점이 있습니다.

  1. 매개 변수 유형을 확인합니다 ( undefined예를 들어, 문자열이 아닌 모든 매개 변수 는str1.toUpperCase() ).
  2. 국제화 문제가 발생하지 않습니다.
  3. RegExp문자열을 이스케이프합니다 .

그러나 정규 표현식 이스케이프가 부족합니다.
Qwertiy

@ Qwertiy 페어 포인트, stackoverflow.com/a/3561711/67824 에 이스케이프가 추가되었습니다 .
하드 슈나이더

0

이것은 이 답변개선 된 버전 입니다 .

String.equal = function (s1, s2, ignoreCase, useLocale) {
    if (s1 == null || s2 == null)
        return false;

    if (!ignoreCase) {
        if (s1.length !== s2.length)
            return false;

        return s1 === s2;
    }

    if (useLocale) {
        if (useLocale.length)
            return s1.toLocaleLowerCase(useLocale) === s2.toLocaleLowerCase(useLocale)
        else
            return s1.toLocaleLowerCase() === s2.toLocaleLowerCase()
    }
    else {
        if (s1.length !== s2.length)
            return false;

        return s1.toLowerCase() === s2.toLowerCase();
    }
}



사용법 및 테스트 :


0

두 가지를 모두 더 낮은 것으로 변환하고 (성능상의 이유로 한 번만) 한 줄로 삼항 연산자와 비교하십시오.

function strcasecmp(s1,s2){
    s1=(s1+'').toLowerCase();
    s2=(s2+'').toLowerCase();
    return s1>s2?1:(s1<s2?-1:0);
}

C가 죽었다고 누가 말합니까? : D
세스

0

ascii텍스트를 다루는 것을 알고 있다면 대문자 / 소문자 오프셋 비교를 사용할 수 있습니다.

문자열을 "완벽한"문자열 (대응하려는 문자열)이 소문자인지 확인하십시오.

const CHARS_IN_BETWEEN = 32;
const LAST_UPPERCASE_CHAR = 90; // Z
function strMatchesIgnoreCase(lowercaseMatch, value) {
    let i = 0, matches = lowercaseMatch.length === value.length;
    while (matches && i < lowercaseMatch.length) {
        const a = lowercaseMatch.charCodeAt(i);
        const A = a - CHARS_IN_BETWEEN;
        const b = value.charCodeAt(i);
        const B = b + ((b > LAST_UPPERCASE_CHAR) ? -CHARS_IN_BETWEEN : CHARS_IN_BETWEEN);
        matches = a === b // lowerA === b
            || A === b // upperA == b
            || a === B // lowerA == ~b
            || A === B; // upperA == ~b
        i++;
    }
    return matches;
}

0

나는이 빠른 속기 변형을 좋아합니다-

export const equalsIgnoreCase = (str1, str2) => {
    return (!str1 && !str2) || (str1 && str2 && str1.toUpperCase() == str2.toUpperCase())
}

처리가 빠르며 의도 한 작업을 수행합니다.


0

javascript 라이브러리는 많은 문자열 작업을 제공하는 것 같습니다. 사용하기 매우 편리합니다

설치하는 방법

npm install --save string

수입

var S = require('string');

무시 문자열 비교

var isEqual = S('ignoreCase').equalsIgnoreCase('IGNORECASE')
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.