정규화된 UTF-8이란 무엇입니까?
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 동등성이 수행되지 않습니다.이 문제가 발생합니다.예를 들어 XML 표준 비교에서는 http://www.w3.org/TR/xml-c14n를 참조하십시오.
이 문제를 피하기 위해...어떤 표준을 사용할까요?"확장 UTF8" 또는 "컴팩트 UTF8"?
"s" 또는 "c+"를 사용합니다.
W3C 및 기타 파일 이름(예: 파일 이름)에서는 "composed as conomical"(가장 컴팩트한 문자열의 C에 유의)을 사용할 것을 제안합니다.그렇게,
기준은 C! NFC 사용 의심
상호운용성 및 "구성보다 규약" 선택에 대해서는 NFC를 사용하여 외부 문자열을 "표준화"할 것을 권고한다.예를 들어 표준 XML을 저장하려면 "FORM_C"에 저장합니다.Web Working Group의 W3C CSV도 NFC를 권장한다(섹션 7.2).
PS: 대부분의 라이브러리에서 "FORM_C"가 기본 형식입니다.예를 들어 PHP의 normalizer.ismormalized()에 있습니다.
합성형(composition form)이라는 용어(FORM_C
)는, 「문자열이 C-표준 형식」(NFC 변환의 결과)이라고 하는 것과 변환 알고리즘이 사용되고 있는 것 양쪽 모두에 익숙합니다.http://www.macchiato.com/unicode/nfc-faq 를 참조해 주세요.
(...) 다음 각 시퀀스(처음 2개는 단일 문자 시퀀스)는 동일한 문자를 나타냅니다.
- U+00C5( å) 위 라틴 대문자 A(고리 포함)
- U+212B(Ω) 앙스트롬 부호
- U+0041 (A) 라틴 대문자 A + U+030A ( ) ) 위 링 조합
이러한 시퀀스를 규범적으로 등가라고 부릅니다.이러한 형태 중 첫 번째는 NFC(Normalization Form C)라고 불리며, 여기서 C는 퇴비를 위한 것이다. (...) 문자열 S를 NFC 형식으로 변환하는 함수는 다음과 같이 축약할 수 있다.
toNFC(S)
단, S가 NFC에 있는지 여부를 테스트하는 것은 다음과 같이 생략됩니다.isNFC(S)
.
주의: 작은 문자열(순수 UTF-8 또는 XML 엔티티 참조)의 정규화를 테스트하려면 이 테스트/정규화 온라인컨버터를 사용합니다.
이것은 사실 꽤 간단합니다.UTF-8은 실제로 동일한 "문자"를 여러 가지 다른 표현으로 표현하고 있습니다(바이트 단위에서는 다르기 때문에 따옴표 안에 문자를 사용합니다만, 실제로는 동일합니다).링크된 문서에 예가 나와 있습니다.
문자 "SCS"는 바이트 시퀀스 0xc387로 나타낼 수 있습니다.그러나 이것은 또한 다음과 같이 나타낼 수 있습니다.C
(0x43) 뒤에 바이트시퀀스 0xcca7이 이어집니다.0xc387과 0x43cca7은 같은 문자라고 할 수 있습니다.동작하는 이유는 0xcca7이 콤비네이션 마크이기 때문입니다.즉, 0xcca7은 그 앞에 있는 문자를 사용합니다(a).C
여기서) 및 변경을 실시합니다.
표준 등가성과 호환성 등가성의 차이점에서는 일반적으로 문자를 살펴봐야 합니다.
그 가치를 통해 의미를 전달하는 글자와 다른 글자를 취해서 바꾸는 글자의 두 종류가 있는데 9는 의미 있는 글자입니다.슈퍼스크립트 takes는 그 의미를 받아들여 프레젠테이션에 의해 변경된다.그래서 그것들은 규범적으로 다른 의미를 가지고 있지만 여전히 기본 문자를 나타냅니다.
표준 동등성은 바이트 시퀀스가 동일한 의미를 가진 동일한 문자를 렌더링하는 것입니다.호환성 동등성은 바이트 시퀀스가 동일한 기본 의미를 가진 다른 문자를 렌더링하는 경우입니다(변경될 수도 있음).9와 are는 모두 "9"를 의미하기 때문에 호환성이 동등하지만, 같은 표현이 아니기 때문에 규범적으로 동등하지 않습니다.
일반 형식(데이터베이스가 아닌 Unicode의 경우)은 주로 분음 마크가 있는 문자를 처리합니다(배타적으로?).Unicode는 U+00C0, "라틴 대문자 A with Grave"와 같이 "빌트인" 분음 기호를 가진 문자를 제공합니다.같은 문자를 "라틴 대문자 A"(U+0041)와 "Combining Grave Accent"(U+0300)로 만들 수 있습니다.즉, 두 시퀀스가 동일한 결과 문자를 생성하더라도 바이트별 비교를 통해 완전히 다른 것으로 나타납니다.
정상화는 그것에 대처하기 위한 시도이다.정규화는 모든 문자를 같은 방법으로 부호화하도록 보증(또는 적어도 시도)합니다.모두 필요에 따라 별도의 분음 기호를 사용하거나 가능한 한 단일 코드 포인트를 사용합니다.비교의 관점에서 보면, 어느 것을 선택하든 크게 중요하지 않습니다. 정규화된 문자열은 다른 정규화된 문자열과 적절히 비교됩니다.
In this case, "compatibility" means compatibility with code that assumes that one code point equals one character. If you have code like that, you probably want to use the compatibility normal form. Although I've never seen it stated directly, the names of the normal forms imply that the Unicode consortium considers it preferable to use separate combining diacritical marks. This requires more intelligence to count the actual characters in a string (as well as things like breaking a string intelligently), but is more versatile.
If you're making full use of ICU, chances are that you want to use the canonical normal form. If you're trying to write code on your own that (for example) assumes a code point equals a character, then you probably want the compatibility normal form that makes that true as often as possible.
If two unicode strings are canonically equivalent the strings are really the same, only using different unicode sequences. For example Ä can be represented either using the character Ä or a combination of A and ◌̈.
If the strings are only compatibility equivalent the strings aren't necessarily the same, but they may be the same in some contexts. E.g. ff could be considered same as ff.
So, if you are comparing strings you should use canonical equivalence, because compatibility equivalence isn't real equivalence.
But if you want to sort a set of strings it might make sense to use compatibility equivalence as the are nearly identical.
Whether canonical equivalence or compatibility equivalence is more relevant to you depends on your application. The ASCII way of thinking about string comparisons roughly maps to canonical equivalence, but Unicode represents a lot of languages. I don't think it is safe to assume that Unicode encodes all languages in a way that allows you to treat them just like western european ASCII.
Figures 1 and 2 provide good examples of the two types of equivalence. Under compatibility equivalence, it looks like the same number in sub- and super- script form would compare equal. But I'm not sure that solve the same problem that as the cursive arabic form or the rotated characters.
The hard truth of Unicode text processing is that you have to think deeply about your application's text processing requirements, and then address them as well as you can with the available tools. That doesn't directly address your question, but a more detailed answer would require linguistic experts for each of the languages you expect to support.
ReferenceURL : https://stackoverflow.com/questions/7931204/what-is-normalized-utf-8-all-about
'source' 카테고리의 다른 글
들여쓰기 오류: unindentent가 외부 들여쓰기 수준과 일치하지 않습니다. (0) | 2022.10.02 |
---|---|
이유, 치명적인 오류: 클래스 'PHPUnit_Framework_'Test Case를 찾을 수 없습니다. (0) | 2022.10.02 |
MySQL에서 하나를 제외한 모든 열을 선택하시겠습니까? (0) | 2022.10.02 |
matplotlib Python 설치 문제 (0) | 2022.10.02 |
캔버스 요소에서 마우스 클릭 좌표를 가져오려면 어떻게 해야 합니까? (0) | 2022.10.02 |