Ich benötige einen Zeichencodierungstrick, um hebräische Akzentzeichen zu entfernen.
Probe vorher
בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֱהֹיִ֑ אֵ֥ת הַשָּׁמַשָּׁיִם וְאֵ֥ת הָאָֽרָֽ
Probe nach
בראשית ברא אלהים את השמים ואת הארץ
Ich benötige einen Zeichencodierungstrick, um hebräische Akzentzeichen zu entfernen.
Probe vorher
בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֱהֹיִ֑ אֵ֥ת הַשָּׁמַשָּׁיִם וְאֵ֥ת הָאָֽרָֽ
Probe nach
בראשית ברא אלהים את השמים ואת הארץ
Antworten:
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):
Aussprache (Punkte, die normalerweise in oder über Buchstaben stehen):
Interpunktion
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 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, 2
wie 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 UNICODE
und ASCII
nur den INT
Wert 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
):
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_SC
passte 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 _BIN
nur die neueren _BIN2
Kollatierungen 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:
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.
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 nvarchar
Ihre Ü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;
Ü ö ò ô å Ä Å É ï
. Daher funktioniert eine Standard-Übersetzungs- / Zuordnungsmethode nicht.
Hier ist, was funktioniert, wenn jemand in der Zukunft will.
function accentHebrewToCleanHebrew($accentHebrew){
//Strip Extras
$search = array("֑", "֒", "֓", "֔", "֕",
"֖", "֗", "֘", "֙", "֚", "֛", "֜",
"֝", "֞", "֟", "֠", "֡", "֢", "֣",
"֤", "֥", "֦", "֧", "֨", "֩", "֪",
"֫", "֬", "֭", "֮", "֯", "ְ", "ֱ",
"ֲ", "ֳ", "ִ", "ֵ", "ֶ", "ַ", "ָ",
"ֹ", "ֺ", "ֻ", "ּ", "ֽ", "־", "ֿ",
"׀", "ׁ", "ׂ", "׃", "ׄ", "ׅ", "׆", "ׇ");
$replace = "";
$cleanHebrew = str_replace($search, $replace, $accentHebrew);
return $cleanHebrew;
}