ICU 프로젝트(현재 PHP 라이브러리도 있음)에는 UTF-8 문자열을 정규화하는 데 필요한 클래스가 포함되어 있어 검색 시 값을 쉽게 비교할 수 있습니다.
하지만, 저는 이것이 어플리케이션에 어떤 의미인지 알아내려고 합니다.예를 들어 “호환성 등가성” 또는 “비교적 등가성” 대신 “표준 등가성”을 원하는 경우는 무엇입니까?
질문에 대한 답변
Unicode 정규화에 대해 알고 싶지 않은 모든 것
표준 정규화
유니코드에는 일부 문자(특히 악센트 문자)를 인코딩하는 여러 방법이 있습니다.표준 정규화는 코드 포인트를 표준 인코딩 형식으로 변경합니다.생성된 코드 포인트는 글꼴 또는 렌더링 엔진의 버그를 제외하고 원래 코드 포인트와 동일하게 표시됩니다.
사용 시기
결과는 동일하기 때문에 입력과 동일한 비트에 대해 결과가 비트화되지 않는 한 저장 또는 표시 전에 문자열에 표준 정규화를 적용하는 것이 항상 안전합니다.
표준 정규화는 NFD와 NFC의 두 가지 형태로 이루어집니다.이 둘은 손실 없이 이 두 가지 형태를 전환할 수 있다는 점에서 동등하다.NFC에서 두 문자열을 비교하는 것은 항상 NFD에서 비교하는 것과 같은 결과를 얻을 것이다.
NFD
NFD는 캐릭터를 완전히 확장합니다.이것은 더 빠른 정규화 형식이지만, 그 결과 더 많은 코드 포인트가 생성됩니다(즉, 더 많은 공간을 사용합니다).
아직 정규화되지 않은 두 문자열을 비교하는 경우 호환성 정규화가 필요한 경우를 제외하고 이 정규화 형식을 사용하는 것이 좋습니다.
근거리 무선 통신
NFD 알고리즘을 실행한 후 가능한 경우 NFC는 코드 포인트를 재결합합니다.이 작업은 시간이 좀 걸리지만 문자열이 짧아집니다.
호환성 정규화
유니코드에는 실제로 속하지 않지만 레거시 문자 집합에서 사용된 많은 문자도 포함되어 있습니다.유니코드에서는 이러한 문자 집합의 텍스트를 유니코드로 처리한 후 손실 없이 다시 변환할 수 있도록 이러한 문자가 추가되었습니다.
호환성 정규화는 이들을 대응하는 “실제” 문자의 시퀀스로 변환하고 정규 정규화도 수행합니다.호환성 정규화 결과가 원본과 동일하지 않을 수 있습니다.
서식 정보가 포함된 문자는 서식 정보가 포함되지 않은 문자로 대체됩니다.예를 들어 캐릭터는⁹
로 변환되다9
포맷의 차이가 없는 것도 있습니다.예를 들어 로마숫자Ⅸ
일반 문자로 변환됩니다.IX
.
이 변환이 실행되면 더 이상 손실 없이 원래 문자 집합으로 변환할 수 없습니다.
사용 시기
Unicode Consortium은 다음과 같은 호환성 정규화를 생각할 것을 제안합니다.ToUpperCase
변환합니다.경우에 따라서는 도움이 될 수도 있지만, 무작정 적용해서는 안 됩니다.
검색 엔진으로 뛰어난 활용 사례를 꼽을 수 있습니다.아마도 다음 검색은 필요하기 때문입니다.9
어울리다⁹
.
사용자에게 호환성 정규화를 적용한 결과를 표시해서는 안 됩니다.
NFKC/NFKD
호환성 정규화 폼은 NFKD와 NFKC의 두 가지 형태로 제공됩니다.NFD와 C의 관계는 동일합니다.
NFKC의 모든 문자열은 본질적으로 NFC에도 포함되며 NFKD 및 NFD에서도 동일합니다.따라서NFKD(x)=NFD(NFKC(x))
,그리고.NFKC(x)=NFC(NFKD(x))
,기타.
결론
확실하지 않으면 표준 정규화를 진행하십시오.적용 가능한 공간/속도 균형 또는 상호 운용에 필요한 사항에 따라 NFC 또는 NFD를 선택합니다.
일부 문자(예: 악센트가 있는 문자)는é
)는 2가지 방법으로 나타낼 수 있습니다.단일 코드 포인트U+00E9
또는 보통 글자 뒤에 조합된 악센트 마크가 붙습니다.U+0065 U+0301
. 정규화는 항상 이를 나타내기 위해 이들 중 하나를 선택한다(NFC의 단일 코드 포인트, NFD의 결합 형식).
여러 개의 기본 문자 시퀀스와 조합 마크(예를 들어 “s, dot below, dot above”)로 나타낼 수 있는 문자의 경우 NFD는 다음 중 하나를 선택합니다(아래가 먼저 표시됨).
호환성 분해에는 “실제로 있어서는 안 되는” 문자가 다수 포함되어 있지만 레거시 인코딩에 사용되었기 때문입니다.통상의 정규화에서는, 이것들을 통합하지 않습니다(라운드 트립의 정합성을 유지하기 위해서).기존의 부호화(베트남어 부호화 제외)는 양쪽 모두를 사용하지 않기 때문에, 조합 폼의 문제는 아닙니다만, 호환성의 정규화는 행해집니다.일부 동아시아 부호화(또는 반각/전각 가타카나와 알파벳)에 나타나는 “kg” 기호나 MacRoman의 “fi” 끈처럼 생각하십시오.
상세한 것에 대하여는, http://unicode.org/reports/tr15/ 를 참조해 주세요.
일반 형식(데이터베이스가 아닌 Unicode의 경우)은 주로 분음 마크가 있는 문자를 처리합니다(배타적으로?).Unicode는 U+00C0, “라틴 대문자 A with Grave”와 같이 “빌트인” 분음 기호를 가진 문자를 제공합니다.같은 문자를 “라틴 대문자 A”(U+0041)와 “Combining Grave Accent”(U+0300)로 만들 수 있습니다.즉, 두 시퀀스가 동일한 결과 문자를 생성하더라도 바이트별 비교를 통해 완전히 다른 것으로 나타납니다.
정상화는 그것에 대처하기 위한 시도이다.정규화는 모든 문자를 같은 방법으로 부호화하도록 보증(또는 적어도 시도)합니다.모두 필요에 따라 별도의 분음 기호를 사용하거나 가능한 한 단일 코드 포인트를 사용합니다.비교의 관점에서 보면, 어느 것을 선택하든 크게 중요하지 않습니다. 정규화된 문자열은 다른 정규화된 문자열과 적절히 비교됩니다.
이 경우 “호환성”은 하나의 코드 포인트가 하나의 문자와 같다고 가정하는 코드와의 호환성을 의미합니다.이와 같은 코드가 있는 경우 호환성 일반 형식을 사용하는 것이 좋습니다.직접 언급한 적은 없지만, 일반 형식의 이름은 Unicode 컨소시엄이 분리된 발음을 조합하여 사용하는 것이 더 낫다고 생각한다는 것을 의미합니다.이를 위해서는 문자열 내의 실제 문자를 세는 데 더 많은 지능이 필요하지만(또한 문자열을 지능적으로 끊는 것) 보다 다재다능합니다.
ICU를 최대한 활용하는 경우 정규 정규 형식을 사용할 수 있습니다.예를 들어 코드 포인트가 문자와 같다고 가정하는 코드를 직접 작성하려면 가능한 한 자주 이를 실현하는 호환성 표준 형식을 사용해야 합니다.
두 개의 유니코드 문자열이 규범적으로 동일한 경우 문자열은 서로 다른 유니코드 시퀀스만 사용합니다.예를 들어 for는 문자 character을 사용하거나 A와 ̈을 조합하여 나타낼 수 있습니다.
문자열이 호환성이 동일한 경우에만 동일한 것은 아니지만 컨텍스트에 따라 다를 수 있습니다.예를 들어 ff는 ff와 같은 것으로 간주할 수 있다.
따라서 문자열을 비교할 경우 표준 동등성을 사용해야 합니다. 호환성 동등성은 실제 동등성이 아니기 때문입니다.
그러나 문자열 세트를 정렬하는 경우 가 거의 동일하므로 호환성 동등성을 사용하는 것이 좋을 수 있습니다.
이것은 사실 꽤 간단합니다.UTF-8은 실제로 동일한 “문자”를 여러 가지 다른 표현으로 표현하고 있습니다(바이트 단위에서는 다르기 때문에 따옴표 안에 문자를 사용합니다만, 실제로는 동일합니다).링크된 문서에 예가 나와 있습니다.
문자 “SCS”는 바이트 시퀀스 0xc387로 나타낼 수 있습니다.그러나 이것은 또한 다음과 같이 나타낼 수 있습니다.C
(0x43) 뒤에 바이트시퀀스 0xcca7이 이어집니다.0xc387과 0x43cca7은 같은 문자라고 할 수 있습니다.동작하는 이유는 0xcca7이 콤비네이션 마크이기 때문입니다.즉, 0xcca7은 그 앞에 있는 문자를 사용합니다(a).C
여기서) 및 변경을 실시합니다.
표준 등가성과 호환성 등가성의 차이점에서는 일반적으로 문자를 살펴봐야 합니다.
그 가치를 통해 의미를 전달하는 글자와 다른 글자를 취해서 바꾸는 글자의 두 종류가 있는데 9는 의미 있는 글자입니다.슈퍼스크립트 takes는 그 의미를 받아들여 프레젠테이션에 의해 변경된다.그래서 그것들은 규범적으로 다른 의미를 가지고 있지만 여전히 기본 문자를 나타냅니다.
표준 동등성은 바이트 시퀀스가 동일한 의미를 가진 동일한 문자를 렌더링하는 것입니다.호환성 동등성은 바이트 시퀀스가 동일한 기본 의미를 가진 다른 문자를 렌더링하는 경우입니다(변경될 수도 있음).9와 are는 모두 “9”를 의미하기 때문에 호환성이 동등하지만, 같은 표현이 아니기 때문에 규범적으로 동등하지 않습니다.