Разбор на арабски / RTL текст отляво надясно

Да кажем, че имам низ на RTL език, като например арабски, с добавен малко английски:

string s = "Test:لطيفة;اليوم;a;b"

Забележете, че в низа има точка и запетая. Когато използвам командата Split като string[] spl = s.Split(';');, тогава някои от низовете се записват в обратен ред. Ето какво се случва:

‏‏‏‏‏spl[0] = "‏Тест:لطيفة"
spl[1] = "‏"اليوم
spl[2] = ‏"a"
spl[3] = ‏" б"

Горното не е в ред в сравнение с оригинала. Вместо това очаквам да получа това:

‏‏spl[0] = ‏"Тест:اليوم"
spl[1] = "‏لطيفة"
spl[2] = ‏"a"
spl[3] = ‏"b"

Готов съм да напиша собствена функция за разделяне. Знаците в низа обаче също се анализират в обратен ред, така че се връщам на изходна позиция. Просто искам да мина през всеки знак, както е показано на екрана.


person Dan W    schedule 27.09.2012    source източник


Отговори (4)


Във вида на вашия низ в момента думата لطيفة се съхранява преди думата اليوم; фактът, че اليوم се показва "първи" (т.е. по-наляво), е просто (правилен) резултат от двупосочния алгоритъм на Unicode при показване на текста.

Тоест: низът, с който започвате („Тест:لطيفة;اليوم;a;b“) е резултат от въвеждането на потребителя „Тест:“, след това لطيفة, след това „;“, след това اليوم и след това „;a; б". По този начин начинът, по който C# го разделя, всъщност отразява начина, по който е създаден низът. Просто начинът, по който е създаден, не се отразява в показването на низа, защото двете последователни арабски думи се третират като една единица, когато се показват.

Ако искате низ да показва арабски думи в ред отляво надясно с точка и запетая между тях, като същевременно съхранява думите в същия ред, тогава трябва да поставите знак отляво надясно (U+200E) след точка и запетая. Това ефективно ще раздели всяка арабска дума като отделна единица и двупосочният алгоритъм след това ще третира всяка дума отделно.

Например, следният код започва с низ, идентичен на този, който използвате (с добавяне на единичен знак отляво надясно), но той ще го раздели според начина, по който очаквате (т.е. , spl[0] = ‏"Тест:اليوم" и spl[1] = "‏لطيفة"):

static void Main(string[] args) {
    string s = "Test:اليوم;\u200Eلطيفة;a;b";
    string[] spl = s.Split(';');
}
person Avi Shmidman    schedule 01.10.2012
comment
Благодаря ти! Сега всичко има смисъл. Да, направих грешката да си помисля, че дисплеят го показва „правилно“ (от моя гледна точка). \u200e не променя начина, по който се съхранява вътрешно, а само начина, по който се показва. Запазих привидно неправилния CSV (с данни, които се появяват под грешните заглавки на колони), заредих го в Excel и данните във всяка клетка бяха позиционирани под правилните заглавки! Просто ще трябва да внимавам с U+200E символа, тъй като трябва да го огранича до RTL символи, както е казано другаде. Иска ми се Unicode/VS да направи \u200E начина стил по подразбиране в тези случаи. - person Dan W; 02.10.2012

Можете също да използвате Uniscribe библиотеката на Microsoft. Методът ScriptItemize ще ви даде клъстери от символи, техния начален индекс в оригиналния низ и RTL реда. Използвайки тази информация, можете да намерите последователни клъстери, които съдържат само арабски. Разделяйки ги по отношение на ';' и обръщането на посоката ще ви даде това, от което се нуждаете.

person i_han    schedule 02.10.2012

Те не са обърнати, но всъщност са разделени в правилния ред. RTL езиците са RTL, когато се показват, но в паметта те се съхраняват "отляво надясно" точно като английския. Ще се опитам да демонстрирам, което е малко трудно, тъй като нямам инсталирана арабска клавиатура.

Вашият низ е s = "Arbi/Arbi, Alarbia". s[0] е A (арабското A'in), s[1] е R и така нататък. s[4] е /, а s[9] е , . Така че при разделянето получавате s[0:8] в първата част и s[10:] във втората.

Това е правилният начин за обработка на RTL низове. Ако искате обратното, трябва сами да обърнете масива.

Имайте предвид, че превключването между RTL и LTR е една от най-разочароващите задачи. Нямате представа колко време ще прекарате, за да разберете какво да правите с числа или английски думи в RTL низове. Най-доброто нещо, което можете да направите, е да избегнете проблема напълно и просто да се опитате да накарате Excel да показва низовете като RTL.

person zmbq    schedule 27.09.2012
comment
Само в случай, че съм ви разбрал погрешно, не искам да обърна съдържанието във всеки низ, а само реда на самите низове. За съжаление все още изисквам LTR анализ, за ​​да поддържам съвместимост с потенциален LTR текст в CSV. - person Dan W; 28.09.2012
comment
Ако обърнете самия низ, ще получите обърнати думи, които не означават нищо. Ибра не е същото като Арби, а айбрала дори не е дума. - person zmbq; 28.09.2012
comment
Да, не искам да обръщам нито един низ, а само реда на токените. - person Dan W; 28.09.2012
comment
Редактирах въпроса си допълнително (и го съкратих), така че можете да видите по-дълбокия проблем. Кажи ми какво мислиш. Благодаря за вашата помощ. - person Dan W; 28.09.2012
comment
Можете да разделите низа на всеки знак, който не е буквено-цифров знак и след това да комбинирате и организирате правилно частите (ако е запетая, обърнете реда, ако не - просто комбинирайте). Ще бъде трудно да се оправи. Най-добрият начин е да накарате вашите потребители да въвеждат низа в правилния ред в Excel. Не навлизайте в такива проблеми с RTL, ще получите милион грешки. - person zmbq; 28.09.2012
comment
Благодаря за предупреждението. Съгласен съм, че опитът да го поправя сам може да бъде голяма загуба на време (сигурен съм, че само хвърляйки поглед върху двупосочния алгоритъм на unicode, ще сънувам кошмари цял месец). За съжаление, ако вземете да речем vCard на арабски, ще има точно този проблем, при който английският е последван от арабски текст и след това последван от още малко английски. На първо място е „правилно“, просто не когато се опитвам да го анализирам. - person Dan W; 28.09.2012

Изглежда (според Reflector), че Split вътрешно използва Substring и това използва вътрешна функция, която просто копира букви отляво надясно, без да се съобразява с културата. Поради това не виждам начин просто да обърна масива, който Split връща.

person Patrick Quirk    schedule 27.09.2012
comment
Благодаря. Проблемът идва, когато имам и текст в CSV, който използва „нормалното“ LTR форматиране. Така че, ако обърна масива, има риск редът на низовете, съдържащи „нормален“ текст, също да бъде обърнат. Сам бих го анализирал символ по знак, но проблемът съществува и там, тъй като текстът се анализира от RTL с RTL текст. - person Dan W; 28.09.2012
comment
Редактирах въпроса си, за да изясня проблема. - person Dan W; 28.09.2012