如何去除希伯来语重音标记


17

我需要一个Char编码技巧来去除希伯来语重音标记。

样品之前

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

采样后

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

Answers:


26

这里的技巧是要认识到您在问题中看到的带有“重音符号”的这些字符并不是真的 ”的这些字符字符(即“这些不是机器人您要查找的字符“ ;-))。”重音符号“是各种类型的表示法,它们表示:

  • 元音(通常在字母下方的线和点):

    基本字母“ה” =“ h”;“הֶ” =“ heh”和“הָ” =“ hah”

  • 发音(通常在字母内部或上方的点):

    “בּ” =“ b” vs“ב” =“ v”,或“שׂ” =“ s” vs“שׁ” =“ sh”

  • 标点

  • 滴灌(应该如何播出)

实际的希伯来字母是精简版本中显示的内容(即,此处要求的最终结果)。我们这里所说的“重音符号”被称为变音标记。Wikipedia上有关希伯来变音符号的文章提供了很多有关这些标记的信息,包括以下图像和标题:

创1:9上帝说:“让水被收集”
创1:9上帝说:“让水被收集”。黑色字母,红色,蓝色代表

从这些基本字符到第一行(带有元音等)显示的内容是添加一个或多个“重音符号”的问题。Unicode(SQL Server中的UTF-16,尽管默认解释仅处理UCS-2 /基本多语言平面(BMP)代码点),使某些字符在相邻时可以覆盖另一个非覆盖字符。这些被称为组合字符

含义:

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

返回值:

6

不像2大多数人期望的那样,看到一个双字节字符。因此,也许我们尝试通过执行以下操作找到其中的角色:

SELECT UNICODE(N'מַ֖');

返回:

1502

当然,UNICODEand ASCII函数仅返回INT给定的任何字符串的第一个字符的值。但是1502的值仅覆盖2个字节,这使4个字节无法说明。查看相同希伯来语“字符”的二进制/十六进制值:

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

我们得到:

מ
0x05DE  0xDE05B7059605

现在,0x05DE是1502的十六进制表示,而1502只是“ מ ”。下一部分可以分成三个2个字节的集合:DE05 B705 9605。现在,Unicode字符串值存储在Little Endian中,这意味着字节顺序是相反的。如果我们切换这三个集合,我们将得到:

05DE(基本字符)05B7 0596(未 4个字节)。

好。那么,如果我们删除该基本字符会怎样?

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_BINHebrew_BIN2Latin1_General_BIN,和Latin1_General_BIN2。在函数中,我最终使用Hebrew_BIN2。请注意,在使用二进制归类时,除非您有特殊的需要使用较旧的_BIN归类,否则应仅使用较新的_BIN2归类。

  • 对于任何好奇的人,希伯来语示例文本实际上是Bereishis 1:1(这也是从右到左阅读希伯来语时右侧的第一个单词;尽管在英语中为“创世记1:1”)那不是单词的直接翻译,只是《摩西五经》 /《圣经》第一本书的名称;直接翻译是“开头”):

    在上帝创造天地的初期

  • 2015年1月19日:我发现了一些很棒的资源,可以解释组合字符和希伯来字符集:


@Kin谢谢!(再次:)。让我们看看您的评论这次可以保留多长时间;-D(注意我们的幽灵清理“过程”:但这并不意味着粗鲁或sn亵的含意,带有笑容的笑脸证明😇和这只微笑的猫😺一样)
Solomon Rutzky 2015年

1
再一次,我从你的答案中学到了一些意想不到的东西。真好!
Max Vernon

1
哇!一个不错的语言学答案,并给出了处理编码的出色说明!谢谢,所罗门!
Mike Williamson

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
回复:“试图找到想要的带重音符号的字符,它们似乎没有出现”,这是因为它们不存在;-)。我将在答案中进行更详细的说明,但基本上,它是一个基本字符,带有一个或两个覆盖字符,它们与基本字符占据相同的可见位置。
所罗门·鲁兹基2014年

3
这太酷了。我从未想过这些标记与字符是分开的。谢谢。
Erik Darling 2014年

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;

迈克尔,希伯来语实际上不是那样工作的。这些都不是真正的“重音符号”以同样的方式,这些都是:Ü ö ò ô å Ä Å É ï。因此,标准的翻译/映射方法将不起作用。
所罗门·鲁兹基2014年

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; }

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.