So entfernen Sie hebräische Akzentzeichen


17

Ich benötige einen Zeichencodierungstrick, um hebräische Akzentzeichen zu entfernen.

Probe vorher

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

Probe nach

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

Antworten:


26

Der Trick hier ist zu erkennen, dass diese Zeichen, die Sie in der Frage mit den "Akzenten" sehen, nicht wirklich die Zeichen sind (dh "Diese sind nicht die"DroidenZeichen, nach denen Sie suchen ";-)). Die" Akzente "sind verschiedene Arten von Notationen, die auf Dinge hinweisen wie:

  • Vokale (Linien und Punkte, die normalerweise unter den Buchstaben stehen):

    Basisbuchstabe "ה" = "h"; "הֶ" = "heh" und "הָ" = "hah"

  • Aussprache (Punkte, die normalerweise in oder über Buchstaben stehen):

    "בּ" = "b" vs "ב" = "v" oder "שׂ" = "s" vs "שׁ" = "sh"

  • Interpunktion

  • Cantillation (wie es gesungen werden sollte)

Die tatsächlichen hebräischen Buchstaben sind die, die in der reduzierten Version angezeigt werden (dh das Endergebnis dessen, was hier angefordert wird). Was wir hier als "Akzente" bezeichnen, nennt man diakritische Zeichen. Der Wikipedia-Artikel über hebräische Diakritiker enthält viele gute Informationen zu diesen Zeichen, darunter das folgende Bild und die folgende Bildunterschrift:

1Mo 1: 9 Und Gott sprach: Lass das Wasser gesammelt werden!
1Mo 1: 9 Und Gott sprach: Lass die Wasser sammeln! Buchstaben in schwarz, zeigen in rot, Cantillation in blau

Um von diesen Basiszeichen zu dem zu gelangen, was in der ersten Zeile (mit den Vokalen usw.) angezeigt wird, müssen ein oder mehrere "Akzente" hinzugefügt werden. In Unicode (UTF-16 in SQL Server, obwohl die Standardinterpretation nur die BMP-Codepunkte (Basic Multilingual Plane) von UCS-2 verarbeitet) können einige Zeichen ein anderes Nicht-Overlay-Zeichen überlagern, wenn sie nebeneinander stehen. Diese werden als Kombinieren von Zeichen bezeichnet .

Bedeutung:

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

Kehrt zurück:

6

Nicht so, 2wie die meisten Leute es von einem Einzelbyte-Doppelbyte erwarten würden. Vielleicht versuchen wir herauszufinden, welcher Charakter da ist:

SELECT UNICODE(N'מַ֖');

was zurückgibt:

1502

Natürlich geben die Funktionen UNICODEund ASCIInur den INTWert des ersten Zeichens der angegebenen Zeichenfolge zurück. Ein Wert von 1502 deckt jedoch nur 2 Byte ab, sodass 4 Byte nicht berücksichtigt werden. Betrachten Sie die Binär- / Hexadezimalwerte desselben hebräischen "Zeichens":

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

wir bekommen:

מ
0x05DE  0xDE05B7059605

Jetzt ist 0x05DE die hexadezimale Darstellung von 1502 und 1502 ist nur das " מ ". : Der nächste Teil kann in drei 2-Byte - Sätze getrennt werden DE05 B705 9605 . Jetzt werden Unicode-Zeichenfolgenwerte in Little Endian gespeichert, was bedeutet, dass die Bytereihenfolge umgekehrt ist. Wenn wir jeden dieser drei Sätze wechseln, erhalten wir:

05DE (das Basiszeichen ) 05B7 0596 (das für 4 Bytes nicht belegte).

In Ordnung. Was passiert also, wenn wir dieses Basiszeichen entfernen?

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

Das gibt die beiden verbleibenden Zeichen zurück (hier nicht leicht zu sehen, daher habe ich die folgende Zeile als Überschrift verwendet, um die Schriftgröße zu erhöhen. Sie können auch die obigen Zeilen ausführen, um sie anzuzeigen REPLACE):

Wenn Sie das מ aus dem מַ֖ entfernen, bleiben unten zwei Zeichen: ַ֖

Daher müssen wir jeden einzelnen Code-Punkt entfernen, der eines dieser "zusätzlichen" kombinierenden Zeichen ist (zu finden unter: http://unicode-table.com/en/search/?q=hebrew ) und der uns verlassen wird mit den Basiszeichen. Wir können das tun über:

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;

Und dann können wir es mit dem Originaltext wie folgt testen:

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

SELECT dbo.RemoveHebrewAccents(@Hebrew);

Kehrt zurück:

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


Zusätzliche Bemerkungen:

  • Technisch gesehen gibt es eine Reihe von Codepunkten zwischen 64298 und 64334, in die einige Vokale und Aussprache- "Akzente" eingebaut sind. Wenn diese behandelt werden müssen, kann dies ein zweiter Schritt in der Funktion sein, um diese Zeichen einfach zu ersetzen.

  • Es scheint, dass diese Akzente, Satzzeichen usw. nur dann übereinstimmen, wenn eine binäre Kollatierung verwendet wird. Sogar das Verwenden Hebrew_100_CS_AS_KS_WS_SCpasste nicht zu ihnen. Aber die folgende tat Arbeit: Hebrew_BIN, Hebrew_BIN2, Latin1_General_BIN, und Latin1_General_BIN2. In der Funktion landete ich mit Hebrew_BIN2. Beachten Sie, dass Sie bei der Verwendung von binären Kollatierungen _BINnur die neueren _BIN2Kollatierungen verwenden sollten , es sei denn, Sie müssen die älteren Kollatierungen verwenden.

  • Für alle, die neugierig sind, ist der hebräische Beispieltext tatsächlich Bereishis 1: 1 (das ist auch das erste Wort auf der rechten Seite, da Hebräisch von rechts nach links gelesen wird. Auf Englisch wäre es jedoch "Genesis 1: 1" das ist keine direkte Übersetzung des Wortes, nur der Name des ersten Buches der Thora / Bibel, die direkte Übersetzung ist "am Anfang"):

    Zu Beginn schuf Gott Himmel und Erde

  • 19.01.2015: Ich habe einige großartige Ressourcen gefunden, die sowohl Combining Characters als auch den hebräischen Zeichensatz erklären:


@ Kin Danke! (nochmal :). Mal sehen, wie lange dein Kommentar dieses Mal überlebt ;-D (Hinweis zu unserem "Prozess" der Geisterbereinigung: Das sollte keine unhöflichen oder hinterhältigen Auswirkungen haben, und dieser Smiley mit Heiligenschein beweist, dass 😇 genau wie diese lächelnde Katze 😺)
Solomon Rutzky

1
und wieder lerne ich etwas Unerwartetes aus deinen Antworten. Nett!
Max Vernon

1
Beeindruckend! Eine nette linguistische Antwort mit einer hervorragenden Beschreibung des Umgangs mit Kodierung! Danke, Solomon!
Mike Williamson

1

Dies ist ein interessantes Problem, und eines, mit dem ich vor einiger Zeit konfrontiert war, als ich mit japanischen Schriftzeichen arbeitete. Ich bin gegen eine kleine Mauer gestoßen und habe versucht, Ihre Problemcharaktere zu finden, aber ich hoffe, das bringt Sie dazu, sie zu finden.

Zuerst habe ich alle NCHARs in eine Tabelle eingetragen:

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

Dann habe ich eine der nicht akzentuierten Zeichen gefunden:

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

Dann habe ich den Zeichenbereich gefunden, in dem sich die hebräischen Zeichen befinden:

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

Aber wenn Sie versuchen, die gewünschten Zeichen mit Akzent zu finden, werden sie anscheinend nicht angezeigt, außer bei einem Treffer bei Code 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

Wenn ich nur die umgebenden Zeichen betrachte, kann ich keine anderen Übereinstimmungen mit Ihrem Text identifizieren.

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

Viele von ihnen scheinen als diese nebligen kleinen Rechtecke von was auch immer geworfen zu werden.

Auch hier ist es leider keine Lösung, aber ich hoffe, es hilft.


1
re: "versuche die gewünschten akzentuierten Zeichen zu finden, sie scheinen nicht zu erscheinen", das liegt daran, dass sie nicht existieren ;-). Ich erkläre dies in meiner Antwort ausführlicher, aber im Grunde handelt es sich um ein Basiszeichen mit einem oder zwei Überlagerungszeichen, die dieselbe sichtbare Position wie das Basiszeichen einnehmen.
Solomon Rutzky

3
Das ist wirklich cool. Ich hätte nie gedacht, dass diese Zeichen von den Zeichen getrennt sind. Vielen Dank.
Erik Darling

1

Ich habe eine Nummerntabelle verwendet. Es gibt eine beliebige Anzahl von Beiträgen, die erklären, was dies ist, warum es nützlich ist und wie man es effizient bekommt.

Ich verwende keine eingebaute Funktionalität, um Zeichen mit Akzent in das nicht akzentuierte Äquivalent umzuwandeln. Stattdessen erstelle ich eine Suchliste, in die Sie die gewünschten Conversions eintragen. Sie müssen nvarcharIhre Übersetzungen N'x'natürlich als verwenden und definieren .

Vielen Dank an diesen Beitrag für den Tipp zur Zeilenverkettung.

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;

Michael, Hebräisch funktioniert nicht wirklich so. Diese sind nicht wirklich „Zeichen mit Akzent“ auf die gleiche Art und Weise , dass diese sind: Ü ö ò ô å Ä Å É ï. Daher funktioniert eine Standard-Übersetzungs- / Zuordnungsmethode nicht.
Solomon Rutzky

0

Hier ist, was funktioniert, wenn jemand in der Zukunft will.

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

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.