Come eliminare i segni di accento ebraico


17

Ho bisogno di un trucco per la codifica dei caratteri per eliminare i segni di accento ebraico.

Campione prima

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

Esempio dopo

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

Risposte:


26

Il trucco qui è rendersi conto che questi personaggi che vedi nella domanda con gli "accenti" non sono davvero i personaggi (cioè "Questi non sono idroidipersonaggi che stai cercando ";-)). Gli" accenti "sono vari tipi di notazioni che indicano cose come:

  • vocali (linee e punti che sono in genere sotto le lettere):

    lettera di base "ה" = "h"; "הֶ" = "heh" e "הָ" = "hah"

  • pronuncia (punti che di solito sono dentro o sopra le lettere):

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

  • punteggiatura

  • cantillazione (come dovrebbe essere cantata)

Le lettere ebraiche effettive sono ciò che viene mostrato nella versione ridotta (ovvero il risultato finale di ciò che viene richiesto qui). Ciò a cui ci riferiamo qui come "accenti" sono noti come segni diacritici. L'articolo di Wikipedia sui segni diacritici ebraici contiene molte buone informazioni su questi marchi, tra cui la seguente immagine e didascalia:

Gen. 1: 9 E Dio disse: "Lascia che le acque siano raccolte"
Gen. 1: 9 E Dio disse: "Lasciate che le acque siano raccolte". Lettere in nero, punta in rosso, cantillazione in blu

Passare da quei personaggi di base a ciò che mostra la prima riga (con le vocali, ecc.) È una questione di aggiungere uno o più "accenti". Unicode (UTF-16 in SQL Server, sebbene l'interpretazione predefinita gestisca solo i punti di codice UCS-2 / Basic Multilingual Plane (BMP)) consente ad alcuni caratteri di sovrapporre un altro carattere non sovrapposto quando adiacenti ad essi. Questi sono conosciuti come Combinare personaggi .

Senso:

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

Ritorna:

6

non 2come la maggior parte delle persone si aspetterebbe di vedere un singolo carattere a doppio byte. Quindi forse proviamo a trovare quale personaggio è lì facendo:

SELECT UNICODE(N'מַ֖');

che ritorna:

1502

Naturalmente, le funzioni UNICODEe ASCIIrestituiscono solo il INTvalore del primo carattere di qualunque stringa venga loro assegnata. Ma un valore di 1502 copre solo 2 byte, il che lascia 4 byte non considerati. Guardando i valori binari / esadecimali dello stesso "personaggio" ebraico:

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

noi abbiamo:

מ
0x05DE  0xDE05B7059605

Ora, 0x05DE è la rappresentazione esadecimale di 1502 e il 1502 è solo il " מ ". La parte successiva può essere separata in tre set da 2 byte: DE05 B705 9605 . Ora, i valori di stringa Unicode sono memorizzati in Little Endian, il che significa che l'ordine dei byte è invertito. Se cambiamo ciascuno di questi tre set otteniamo:

05DE (il carattere di base) 05B7 0596 (il non rappresentato per 4 byte).

Ok. Quindi cosa succede se rimuoviamo quel personaggio base?

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

Ciò restituisce i due caratteri rimanenti (non è facile da vedere qui, quindi ho fatto della riga seguente un'intestazione per aumentare la dimensione del carattere; puoi anche eseguire quanto sopra REPLACE per vederli):

La rimozione di מ da מַ֖ lascia due caratteri in basso: ַ֖

Quindi, dobbiamo eliminare ogni singolo punto di codice che è uno di questi caratteri "extra" combinati (disponibile su: http://unicode-table.com/en/search/?q=hebrew ) e che ci lascerà con i personaggi di base. Possiamo farlo tramite:

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;

E quindi possiamo provarlo con il testo originale come segue:

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

SELECT dbo.RemoveHebrewAccents(@Hebrew);

Ritorna:

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


Note aggiuntive:

  • Tecnicamente, esiste un set di punti di codice tra 64298 e 64334 che ne hanno alcuni vocali e "accenti" di pronuncia incorporati nel personaggio. Se questi devono essere gestiti, questo può essere un secondo passo nella funzione per fare una semplice sostituzione di quei caratteri.

  • Sembra che questi punti di accento, punteggiatura, ecc. Coincidano solo quando si usano le regole di confronto binarie. Anche usando Hebrew_100_CS_AS_KS_WS_SCnon li ha abbinati. Ma il seguente ha funzionato: Hebrew_BIN, Hebrew_BIN2, Latin1_General_BIN, e Latin1_General_BIN2. Nella funzione ho finito per usare Hebrew_BIN2. Si noti che quando si utilizzano le regole di confronto binarie, a meno che non si abbia una necessità specifica di utilizzare le _BINregole di confronto precedenti , è necessario utilizzare solo le _BIN2regole di confronto più recenti .

  • Per chiunque sia curioso, il testo di esempio ebraico è in realtà Bereishis 1: 1 (che è anche la prima parola sul lato destro poiché l'ebraico viene letto da destra a sinistra; in inglese sarebbe "Genesi 1: 1" anche se quella non è una traduzione diretta della parola, solo il nome del primo libro della Torah / Bibbia; la traduzione diretta è "all'inizio"):

    All'inizio della creazione di Dio nei cieli e nella Terra

  • 19/01/2015: ho trovato delle risorse straordinarie che spiegano sia la combinazione di personaggi che il set di caratteri ebraico:


@Kin grazie! (ancora :). Vediamo per quanto tempo il tuo commento sopravvive stavolta ;-D (nota per il nostro "processo" di pulizia dei fantasmi: quello non doveva avere implicazioni maleducate o malandate, e questa faccina con aureola dimostra che 😇 come fa questo gatto sorridente 😺)
Solomon Rutzky il

1
e di nuovo imparo qualcosa di inaspettato dalle tue risposte. Bello!
Max Vernon,

1
Wow! Una bella risposta linguistica integrata con un'eccellente descrizione della gestione della codifica! Grazie, Salomone!
Mike Williamson,

1

Questo è un problema interessante, e ho dovuto affrontare un po 'di tempo lavorando con personaggi giapponesi. Ho colpito un po 'di un muro di mattoni nel tentativo di individuare i personaggi problematici, anche se spero che questo ti porti da qualche parte a trovarli.

Per prima cosa ho messo tutti gli NCHAR in un tavolo:

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

Quindi ho individuato uno dei caratteri non accentati:

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

Quindi ho trovato la gamma di caratteri in cui si trovano i personaggi ebraici:

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

Ma cercando di trovare i caratteri accentati che desideri, non sembrano comparire, tranne un colpo al codice 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

Quindi, solo guardando i personaggi circostanti, non riesco davvero a identificare altre corrispondenze al tuo testo.

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

Molti di loro sembrano essere lanciati come quei piccoli rettangoli nebulosi di qualunque cosa.

Ancora una volta, scusa non è una soluzione, ma spero che sia di aiuto.


1
ri: "cercando di trovare i caratteri accentati che vuoi, non sembrano apparire", perché non esistono ;-). Spiego più in dettaglio nella mia risposta, ma fondamentalmente è un personaggio base con uno o due personaggi sovrapposti che assumono la stessa posizione visibile del personaggio base.
Solomon Rutzky il

3
È davvero fantastico. Non avrei mai pensato che quei segni fossero separati dai personaggi. Grazie.
Erik Darling,

1

Ho usato una tabella dei numeri. Ci sono molti post che spiegano di cosa si tratta, perché sono utili e come ottenerne uno in modo efficiente.

Non utilizzo alcuna funzionalità integrata per convertire i caratteri accentati in equivalenti non accentati. Invece, creo un elenco di ricerca che popolerai con le conversioni richieste. Dovrai utilizzare nvarchare definire le tue traduzioni comeN'x' , ovviamente.

Grazie a questo post per il suggerimento di concatenazione delle righe.

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, l'ebraico in realtà non funziona in questo modo. Questi non sono "caratteri accentati" veramente nello stesso modo in cui questi sono: Ü ö ò ô å Ä Å É ï. Pertanto, un metodo di traduzione / mappatura standard non funzionerà.
Solomon Rutzky,

0

Ecco cosa ha funzionato se qualcuno in futuro lo desidera.

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.