나는 놀라운 문제에 빠진다.
내 응용 프로그램에 텍스트 파일을로드했고 µ 값을 비교하는 논리가 있습니다.
그리고 나는 텍스트가 동일하더라도 비교 값이 거짓임을 깨달았습니다.
Console.WriteLine("μ".Equals("µ")); // returns false
Console.WriteLine("µ".Equals("µ")); // return true
뒷줄에서 문자 µ는 복사 붙여 넣기됩니다.
그러나 이것들은 이와 같은 유일한 캐릭터가 아닐 수도 있습니다.
C #에서 동일하게 보이지만 실제로 다른 문자를 비교할 수있는 방법이 있습니까?
답변
많은 경우에, 당신은 할 수 있습니다 정상화 를 비교하기 전에 특정 정상화 폼에 유니 코드 문자를 모두, 그들은 일치 할 수 있어야한다. 물론 어떤 정규화 형식을 사용해야하는지는 문자 자체에 따라 다릅니다. 단지 그들이 때문에 볼 필요가 같은 문자를 나타내는 의미하지 않는다 모두. 또한 사용 사례에 적합한 지 고려해야합니다. Jukka K. Korpela의 의견을 참조하십시오.
이 특정 상황에서 Tony ‘s answer 의 링크를 참조하면 U + 00B5에 대한 표에 다음과 같은 내용이 표시됩니다 .
분해 <compat> GREEK SMALL LETTER MU (U + 03BC)
즉, 원래 비교에서 두 번째 문자 인 U + 00B5를 첫 번째 문자 인 U + 03BC로 분해 할 수 있습니다.
따라서 정규화 형식 KC 또는 KD와 함께 완전한 호환성 분해를 사용하여 문자를 정규화합니다. 다음은 내가 시연하기 위해 작성한 간단한 예입니다.
using System;
using System.Text;
class Program
{
static void Main(string[] args)
{
char first = 'μ';
char second = 'µ';
// Technically you only need to normalize U+00B5 to obtain U+03BC, but
// if you're unsure which character is which, you can safely normalize both
string firstNormalized = first.ToString().Normalize(NormalizationForm.FormKD);
string secondNormalized = second.ToString().Normalize(NormalizationForm.FormKD);
Console.WriteLine(first.Equals(second)); // False
Console.WriteLine(firstNormalized.Equals(secondNormalized)); // True
}
}
유니 코드 정규화 및 다양한 정규화 형식에 대한 자세한 내용은 System.Text.NormalizationForm
및 유니 코드 사양을 참조하십시오 .
답변
똑같아도 정말 다른 기호이기 때문에 첫 번째는 실제 문자이고 char가 code = 956 (0x3BC)
있고 두 번째는 마이크로 기호이며 181 (0xB5)
.
참조 :
따라서 이들을 비교하고 동일해야하는 경우 수동으로 처리하거나 비교하기 전에 한 문자를 다른 문자로 대체해야합니다. 또는 다음 코드를 사용하십시오.
public void Main()
{
var s1 = "μ";
var s2 = "µ";
Console.WriteLine(s1.Equals(s2)); // false
Console.WriteLine(RemoveDiacritics(s1).Equals(RemoveDiacritics(s2))); // true
}
static string RemoveDiacritics(string text)
{
var normalizedString = text.Normalize(NormalizationForm.FormKC);
var stringBuilder = new StringBuilder();
foreach (var c in normalizedString)
{
var unicodeCategory = CharUnicodeInfo.GetUnicodeCategory(c);
if (unicodeCategory != UnicodeCategory.NonSpacingMark)
{
stringBuilder.Append(c);
}
}
return stringBuilder.ToString().Normalize(NormalizationForm.FormC);
}
그리고 데모
답변
둘 다 다른 문자 코드를 가지고 있습니다. 자세한 내용은 이것을 참조하십시오.
Console.WriteLine((int)'μ'); //956
Console.WriteLine((int)'µ'); //181
첫 번째는 다음과 같습니다.
Display Friendly Code Decimal Code Hex Code Description
====================================================================
μ μ μ μ Lowercase Mu
µ µ µ µ micro sign Mu
답변
μ
(mu) 및 µ
(마이크로 기호) 의 특정 예의 경우 후자는 전자에 대한 호환성 분해 가 있으므로 문자열을 정규화FormKC
하거나 FormKD
마이크로 기호를 mus로 변환 할 수 있습니다 .
그러나 비슷해 보이지만 유니 코드 정규화 형식에서는 동일하지 않은 문자 집합이 많이 있습니다. 예를 들어, A
(Latin), Α
(Greek) 및 А
(Cyrillic)입니다. 유니 코드 웹 사이트에는 개발자들이 동형 이의어 공격으로부터 보호 할 수 있도록 돕기 위해 이들 목록 이 포함 된 confusables.txt 파일이 있습니다. 필요한 경우이 파일을 구문 분석하고 문자열의 “시각적 정규화”를위한 테이블을 만들 수 있습니다.
답변
유니 코드 데이터베이스 에서 두 문자를 모두 검색 하고 차이점을 확인하십시오 .
하나는 그리스 소문자 µ
이고 다른 하나는 마이크로 기호 µ
입니다.
Name : MICRO SIGN Block : Latin-1 Supplement Category : Letter, Lowercase [Ll] Combine : 0 BIDI : Left-to-Right [L] Decomposition : <compat> GREEK SMALL LETTER MU (U+03BC) Mirror : N Index entries : MICRO SIGN Upper case : U+039C Title case : U+039C Version : Unicode 1.1.0 (June, 1993)
Name : GREEK SMALL LETTER MU Block : Greek and Coptic Category : Letter, Lowercase [Ll] Combine : 0 BIDI : Left-to-Right [L] Mirror : N Upper case : U+039C Title case : U+039C See Also : micro sign U+00B5 Version : Unicode 1.1.0 (June, 1993)
답변
편집 이 질문을 C #에서 ‘μ’와 ‘µ’를 비교하는 방법 과 병합 한 후
게시 된 원래 답변 :
"μ".ToUpper().Equals("µ".ToUpper()); //This always return true.
편집
주석을 읽은 후에는 다른 유형의 입력에 대해 잘못된 결과를 제공 할 수 있기 때문에 위의 방법을 사용하는 것은 좋지 않습니다.이 때문에 위키 에서 언급 한대로 완전한 호환성 분해를 사용하여 정규화 를 사용해야합니다 . ( BoltClock이 게시 한 답변에 감사드립니다 )
static string GREEK_SMALL_LETTER_MU = new String(new char[] { '\u03BC' });
static string MICRO_SIGN = new String(new char[] { '\u00B5' });
public static void Main()
{
string Mus = "µμ";
string NormalizedString = null;
int i = 0;
do
{
string OriginalUnicodeString = Mus[i].ToString();
if (OriginalUnicodeString.Equals(GREEK_SMALL_LETTER_MU))
Console.WriteLine(" INFORMATIO ABOUT GREEK_SMALL_LETTER_MU");
else if (OriginalUnicodeString.Equals(MICRO_SIGN))
Console.WriteLine(" INFORMATIO ABOUT MICRO_SIGN");
Console.WriteLine();
ShowHexaDecimal(OriginalUnicodeString);
Console.WriteLine("Unicode character category " + CharUnicodeInfo.GetUnicodeCategory(Mus[i]));
NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormC);
Console.Write("Form C Normalized: ");
ShowHexaDecimal(NormalizedString);
NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormD);
Console.Write("Form D Normalized: ");
ShowHexaDecimal(NormalizedString);
NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormKC);
Console.Write("Form KC Normalized: ");
ShowHexaDecimal(NormalizedString);
NormalizedString = OriginalUnicodeString.Normalize(NormalizationForm.FormKD);
Console.Write("Form KD Normalized: ");
ShowHexaDecimal(NormalizedString);
Console.WriteLine("_______________________________________________________________");
i++;
} while (i < 2);
Console.ReadLine();
}
private static void ShowHexaDecimal(string UnicodeString)
{
Console.Write("Hexa-Decimal Characters of " + UnicodeString + " are ");
foreach (short x in UnicodeString.ToCharArray())
{
Console.Write("{0:X4} ", x);
}
Console.WriteLine();
}
산출
INFORMATIO ABOUT MICRO_SIGN
Hexa-Decimal Characters of µ are 00B5
Unicode character category LowercaseLetter
Form C Normalized: Hexa-Decimal Characters of µ are 00B5
Form D Normalized: Hexa-Decimal Characters of µ are 00B5
Form KC Normalized: Hexa-Decimal Characters of µ are 03BC
Form KD Normalized: Hexa-Decimal Characters of µ are 03BC
________________________________________________________________
INFORMATIO ABOUT GREEK_SMALL_LETTER_MU
Hexa-Decimal Characters of µ are 03BC
Unicode character category LowercaseLetter
Form C Normalized: Hexa-Decimal Characters of µ are 03BC
Form D Normalized: Hexa-Decimal Characters of µ are 03BC
Form KC Normalized: Hexa-Decimal Characters of µ are 03BC
Form KD Normalized: Hexa-Decimal Characters of µ are 03BC
________________________________________________________________
Unicode_equivalence로 정보를 읽는 동안 발견했습니다.
동등성 기준의 선택은 검색 결과에 영향을 줄 수 있습니다. 예를 들어 U + FB03 (ffi), ….. 그래서 U + 0066 (f)를 부분 문자열로 검색 하면 U + FB03 의 NFKC 정규화에서는 성공 하지만 U + FB03의 NFC 정규화에서는 성공 하지 못합니다 .
따라서 동등성을 비교하려면 일반적으로 FormKC
NFKC 정규화 또는 NFKD 정규화를 사용해야합니다 FormKD
.
모든 유니 코드 문자에 대해 더 많이 알고 싶어서별로 궁금하지 않았기 때문에 모든 유니 코드 문자를 반복하는 샘플을 만들었고 UTF-16
논의하고 싶은 결과를 얻었습니다.
FormC
및FormD
정규화 된 값이 동일하지 않은 문자에 대한 정보
Total: 12,118
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-253, ..... 44032-55203
FormKC
및FormKD
정규화 된 값이 동일하지 않은 문자에 대한 정보
Total: 12,245
Character (int value): 192-197, 199-207, 209-214, 217-221, 224-228, ..... 44032-55203, 64420-64421, 64432-64433, 64490-64507, 64512-64516, 64612-64617, 64663-64667, 64735-64736, 65153-65164, 65269-65274
FormC
및FormD
정규화 된 값이 동일하지 않은 모든 문자 , thereFormKC
및FormKD
정규화 된 값도 다음 문자를 제외하고 동일하지 않습니다
.901 '΅', 8129 '῁', 8141 '῍', 8142 '῎', 8143 '῏', 8157 '῝', 8158 '῞'
, 8159 '῟', 8173 '῭', 8174 '΅'
- 추가 캐릭터 그
FormKC
와FormKD
정규화 된 값은 동등하지 않았다, 그러나 거기FormC
와FormD
정규화 값은 상당했다
Total: 119
문자 :452 'DŽ' 453 'Dž' 454 'dž' 12814 '㈎' 12815 '㈏' 12816 '㈐' 12817 '㈑' 12818 '㈒'
12819 '㈓' 12820 '㈔' 12821 '㈕', 12822 '㈖' 12823 '㈗' 12824 '㈘' 12825 '㈙' 12826 '㈚'
12827 '㈛' 12828 '㈜' 12829 '㈝' 12830 '㈞' 12910 '㉮' 12911 '㉯' 12912 '㉰' 12913 '㉱'
12914 '㉲' 12915 '㉳' 12916 '㉴' 12917 '㉵' 12918 '㉶' 12919 '㉷' 12920 '㉸' 12921 '㉹' 12922 '㉺' 12923 '㉻' 12924 '㉼' 12925 '㉽' 12926 '㉾' 13056 '㌀' 13058 '㌂' 13060 '㌄' 13063 '㌇' 13070 '㌎' 13071 '㌏' 13072 '㌐' 13073 '㌑' 13075 '㌓' 13077 '㌕' 13080 '㌘' 13081 '㌙' 13082 '㌚' 13086 '㌞' 13089 '㌡' 13092 '㌤' 13093 '㌥' 13094 '㌦' 13099 '㌫' 13100 '㌬' 13101 '㌭' 13102 '㌮' 13103 '㌯' 13104 '㌰' 13105 '㌱' 13106 '㌲' 13108 '㌴' 13111 '㌷' 13112 '㌸' 13114 '㌺' 13115 '㌻' 13116 '㌼' 13117 '㌽' 13118 '㌾' 13120 '㍀' 13130 '㍊' 13131 '㍋' 13132 '㍌' 13134 '㍎' 13139 '㍓' 13140 '㍔' 13142 '㍖' .......... ﺋ' 65164 'ﺌ' 65269 'ﻵ' 65270 'ﻶ' 65271 'ﻷ' 65272 'ﻸ' 65273 'ﻹ' 65274' - 정규화 할 수없는 문자가 있습니다.
ArgumentException
시도하면 던집니다.
Total:2081
Characters(int value): 55296-57343, 64976-65007, 65534
이 링크는 유니 코드 동등성에 적용되는 규칙을 이해하는 데 매우 유용 할 수 있습니다.
답변
대부분의 경우 동일한 문자를 (가시적으로) 만드는 두 가지 다른 문자 코드가 있습니다. 기술적으로 동일하지는 않지만 동일하게 보입니다. 캐릭터 테이블을보고 해당 캐릭터의 여러 인스턴스가 있는지 확인하십시오. 또는 코드에있는 두 문자의 문자 코드를 인쇄하십시오.