Как убрать еврейский акцент

17

Мне нужен трюк с кодировкой символов, чтобы убрать знаки ударения на иврите.

Образец перед

בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ

Образец после

בראשית ברא אלהים את השמים ואת הארץ

Расшифрованный
источник

Ответы:

26

Фокус в том , чтобы понять , что эти символы , которые вы видите в этом вопросе с «акцентом» не являются на самом деле эти символы (т.е. «Это недроидысимволы, которые вы ищете ";-))." Акценты "- это различные типы обозначений, обозначающих такие вещи, как:

  • гласные (строки и точки, которые обычно находятся под буквами):

    базовая буква "ה" = "h"; "הֶ" = "хех" и "הָ" = "хах"

  • произношение (точки, которые обычно находятся внутри или над буквами):

    "בּ" = "b" против "ב" = "v" или "שׂ" = "s" против "שׁ" = "sh"

  • пунктуация

  • кантилляция (как надо петь)

Фактические ивритские буквы - это то, что показано в урезанной версии (то есть конечный результат того, что запрашивается здесь). То, что мы называем здесь «акцентами», называется диакритическими знаками. В статье Википедии об ивритских диакритиках содержится много полезной информации об этих знаках, включая следующее изображение и подпись:

Быт. 1: 9 И сказал Бог: да соберется вода
Быт. 1: 9 И сказал Бог: да соберется вода. Буквы черного цвета, указывающие красным, кантилляционные синим

Чтобы перейти от этих базовых символов к тому, что показано в первой строке (с гласными и т. Д.), Нужно добавить один или несколько «акцентов». Юникод (UTF-16 в SQL Server, хотя интерпретация по умолчанию обрабатывает только кодовые точки UCS-2 / Базовая многоязычная плоскость (BMP)) позволяет некоторым символам перекрывать другой неперекрывающийся символ, когда они смежны с ними. Они известны как объединение персонажей .

Смысл:

SELECT DATALENGTH(N'מַ֖'); -- character taken from original given text

Возвращает:

6

не так, 2как многие ожидали бы увидеть двухбайтовый символ. Поэтому, возможно, мы попытаемся выяснить, какой персонаж там делает:

SELECT UNICODE(N'מַ֖');

который возвращает:

1502

Конечно, функции UNICODEи ASCIIвозвращают только INTзначение первого символа любой заданной строки. Но значение 1502 покрывает только 2 байта, что оставляет 4 байта неучтенными. Глядя на двоичные / шестнадцатеричные значения того же самого ивритского «символа»:

SELECT NCHAR(1502), CONVERT(BINARY(2), UNICODE(N'מַ֖')), CONVERT(VARBINARY(10), N'מַ֖');

мы получаем:

מ
0x05DE  0xDE05B7059605

Теперь 0x05DE - это шестнадцатеричное представление 1502, а 1502 - это только « מ ». Следующая часть может быть разделена на три двухбайтовых набора: DE05 B705 9605 . Теперь строковые значения Юникода хранятся в Little Endian, что означает обратный порядок байтов. Если мы переключим каждый из этих трех наборов, мы получим:

05DE (базовый символ) 05B7 0596 (неучтенный 4 байта).

Ok. Так что же произойдет, если мы удалим этот базовый символ?

SELECT REPLACE(N'מַ֖' COLLATE Hebrew_BIN2, NCHAR(1502) COLLATE Hebrew_BIN2, '');

Это возвращает два оставшихся символа (это не так легко увидеть, поэтому я сделал следующую строку заголовком, чтобы увеличить размер шрифта; вы также можете запустить выше, REPLACEчтобы увидеть их):

Удаление מ из מַ֖ оставляет два символа внизу: ַ֖

Следовательно, нам нужно убрать каждую отдельную кодовую точку, которая является одним из этих «дополнительных» комбинирующих символов (находится по адресу: http://unicode-table.com/en/search/?q=hebrew ), и это оставит нас с базовыми персонажами. Мы можем сделать это через:

CREATE FUNCTION dbo.RemoveHebrewAccents (@txeTwerbeH NVARCHAR(MAX))
RETURNS NVARCHAR(MAX)
WITH SCHEMABINDING
AS
BEGIN

  WITH base (dummy) AS
  (
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
    SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
  ), nums AS
  (
    -- we will want to generate code points 1425 - 1479
    SELECT TOP (55) ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) AS [Num]
    FROM   base b1
    CROSS JOIN base b2
  )
  SELECT @txeTwerbeH = REPLACE(
                               @txeTwerbeH COLLATE Hebrew_BIN2,
                               NCHAR(1424 + nums.[Num]) COLLATE Hebrew_BIN2,
                               ''
                              )
  FROM   nums;

  RETURN @txeTwerbeH;
END;

И тогда мы можем проверить это с оригинальным текстом следующим образом:

DECLARE @Hebrew NVARCHAR(200) = N'בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ';

SELECT dbo.RemoveHebrewAccents(@Hebrew);

Возвращает:

בראשית ברא אלהים את השמים ואת הארץ


Дополнительные замечания:

  • Технически, существует ряд кодовых точек между 64298 и 64334, которые имеют некоторые гласные и акценты произношения, встроенные в символ. Если их необходимо обработать, это может быть вторым шагом в функции для простой замены этих символов.

  • Кажется, что эти кодовые точки акцента, пунктуации и т. Д. Совпадают только при использовании двоичного сопоставления. Даже использование Hebrew_100_CS_AS_KS_WS_SCне соответствовало им. Но на следующий же работу: Hebrew_BIN, Hebrew_BIN2, Latin1_General_BIN, и Latin1_General_BIN2. В функции, которую я в конечном итоге использовал Hebrew_BIN2. Обратите внимание, что при использовании двоичных сопоставлений, если у вас нет особой необходимости использовать более старые _BINсопоставления, вы должны использовать только более новые _BIN2сопоставления.

  • Любой, кому интересно, образец текста на иврите на самом деле Bereishis 1: 1 (это также первое слово справа, так как иврит читается справа налево; на английском языке это будет «Бытие 1: 1», хотя это не прямой перевод слова, а просто название первой книги Торы / Библии; прямой перевод «в начале»):

    В начале Божьего творения небо и земля

  • 2015-01-19: я нашел несколько замечательных ресурсов, которые объясняют как комбинацию символов, так и набор символов иврита:

Соломон Руцкий
источник
@ Кин Спасибо! (опять таки :). Давайте посмотрим, как долго ваш комментарий выживет на этот раз ;-D (обратите внимание на наш «процесс» очистки призрака: это не должно было иметь каких-либо грубых или грубых последствий, и этот смайлик с ореолом доказывает, что 😇 как и этот улыбающийся кот 😺)
Соломон Руцкий
1
и снова я узнаю что-то неожиданное из ваших ответов. Ницца!
Макс Вернон,
1
Вот это да! Хороший лингвистический ответ с отличным описанием обработки кодирования! Спасибо, Соломон!
Майк Уильямсон
1

Это интересная проблема, с которой я столкнулся некоторое время назад, работая с японскими символами. Я наткнулся на кирпичную стену, пытаясь определить местонахождение ваших проблемных персонажей, хотя я надеюсь, что это поможет вам найти их.

Сначала я собрал все NCHAR в таблицу:

SET NOCOUNT ON  

DECLARE @cnt INT = 1
DECLARE @sqlcmd NVARCHAR(512) = ''

CREATE TABLE #CHARS (
[CharOrder] INT IDENTITY(1,1) PRIMARY KEY CLUSTERED,
[Result] NVARCHAR(4) 
)

WHILE @cnt < 65536
BEGIN

SELECT @sqlcmd = '
INSERT #CHARS
    ([Result] )
SELECT NCHAR(' + CAST(@cnt AS NVARCHAR) + ')
'

EXEC sys.sp_executesql @sqlcmd

SET @cnt +=1 
END

Затем я нашел один из символов без акцента:

SELECT  c.CharOrder, c.Result
FROM    #CHARS AS c
WHERE c.Result = N'ר'
ORDER BY c.CharOrder

Затем я определил диапазон символов, в которых находятся ивритские символы:

SELECT  c.CharOrder, c.Result
FROM    #CHARS AS c
WHERE c.CharOrder >= 1488
AND c.CharOrder < 1523
ORDER BY c.CharOrder

Но, пытаясь найти нужные вам акцентированные символы, они не отображаются, кроме одного попадания в код 8501.

SELECT  c.CharOrder ,
        c.Result
FROM    #CHARS AS c
WHERE   c.Result IN ( N'רֵ', N'א', N'שִׁ֖', N'י', N'ת', N'בְּ', N'בָּ', N'רָ֣',
                      N'א', N'אֱ', N'לֹ', N'הִ֑', N'י', N'ם', N'אֵ֥', N'ת',
                      N'הַ', N'שָּׁ', N'מַ֖', N'יִ', N'ם', N'וְ', N'אֵ֥', N'ת',
                      N'הָ', N'אָֽ', N'רֶ', N'ץ' )
ORDER BY c.CharOrder

Так что, просто глядя на окружающих персонажей, я не могу определить другие совпадения с вашим текстом.

SELECT  c.CharOrder, c.Result
FROM    #CHARS AS c
WHERE c.CharOrder >= 8499
AND c.CharOrder < 8539
ORDER BY c.CharOrder

Кажется, что многие из них выбрасываются в виде этих туманных маленьких прямоугольников.

Опять же, извините, это не решение, но надеюсь, что это поможет.

Эрик Дарлинг
источник
1
Re: «пытаясь найти акцентированные символы, которые вы хотите, они, кажется, не появляются», это потому, что они не существуют ;-). Я объясню более подробно в своем ответе, но в основном это базовый символ с одним или двумя наложенными символами, которые занимают ту же видимую позицию, что и базовый символ.
Соломон Руцкий,
3
Это действительно круто. Я никогда бы не подумал, что эти знаки были отдельными от персонажей. Благодарю.
Эрик Дарлинг
1

Я использовал таблицу чисел. Есть любое количество постов, объясняющих, что это такое, почему это полезно и как эффективно его получить.

Я не использую встроенную функциональность для преобразования символов без акцента в эквивалент без акцента. Вместо этого я создаю список поиска, который вы будете заполнять необходимыми конверсиями. Вы должны будете использовать nvarcharи определять свои переводы как N'x', конечно.

Спасибо за этот пост за конкатенацию строк.

drop table #Numbers;

select
    *
into #Numbers
from 
    (
    select *
    from (values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11)) as T(N)
    ) as xx;

drop table #Lookups;

select
    *
into #Lookups
from 
    (
    select *
    from (values ('a','m'),('b','n'),('c','o'),('d','p'),('e','q'),('m','z')) as T(CharFrom,CharTo)
    ) as xx;


drop table #Inputs;

select
    *
into #Inputs
from 
    (
    select *
    from (values ('abcdefghi')
                ,('abtcd')
        ) as T(Word)
    ) as xx;


select
     ix.Word as Original
    ,(
    select
        Coalesce(l.CharTo, SUBSTRING(i.word, n.N, 1)) -- do not alias
    from #Inputs as i
    cross apply #Numbers as n
    left join #Lookups as l
        on l.CharFrom = SUBSTRING(i.word, n.N, 1)
    where n.N <= LEN(i.Word)
    and i.Word = ix.Word
    for xml path ('')
    ) as Substituted
from #Inputs as ix;
Майкл Грин
источник
Майкл, иврит на самом деле не работает таким образом. Это не по- настоящему «символы с диакритическими знаками» таким же образом , что они являются: Ü ö ò ô å Ä Å É ï. Следовательно, стандартный метод перевода / отображения не будет работать.
Соломон Руцкий,
0

Вот что сработало, если кто-то в будущем захочет.

function accentHebrewToCleanHebrew($accentHebrew){ //Strip Extras $search = array("&#1425;", "&#1426;", "&#1427;", "&#1428;", "&#1429;", "&#1430;", "&#1431;", "&#1432;", "&#1433;", "&#1434;", "&#1435;", "&#1436;", "&#1437;", "&#1438;", "&#1439;", "&#1440;", "&#1441;", "&#1442;", "&#1443;", "&#1444;", "&#1445;", "&#1446;", "&#1447;", "&#1448;", "&#1449;", "&#1450;", "&#1451;", "&#1452;", "&#1453;", "&#1454;", "&#1455;", "&#1456;", "&#1457;", "&#1458;", "&#1459;", "&#1460;", "&#1461;", "&#1462;", "&#1463;", "&#1464;", "&#1465;", "&#1466;", "&#1467;", "&#1468;", "&#1469;", "&#1470;", "&#1471;", "&#1472;", "&#1473;", "&#1474;", "&#1475;", "&#1476;", "&#1477;", "&#1478;", "&#1479;"); $replace = ""; $cleanHebrew = str_replace($search, $replace, $accentHebrew); return $cleanHebrew; }

Расшифрованный
источник