Potrzebuję sztuczki kodowania Char, aby usunąć hebrajskie znaki akcentujące.
Próbka przed
בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ
Próbka po
בראשית ברא אלהים את השמים ואת הארץ
Potrzebuję sztuczki kodowania Char, aby usunąć hebrajskie znaki akcentujące.
Próbka przed
בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ
Próbka po
בראשית ברא אלהים את השמים ואת הארץ
Odpowiedzi:
Sztuką jest, aby zdać sobie sprawę, że te znaki, które widzisz na pytanie z „akcentów” tak naprawdę nie są to znaki (czyli „To nie sądroidyznaki, których szukasz „;-)).„ Akcenty ”to różnego rodzaju notacje wskazujące na:
samogłoski (linie i kropki, które zwykle znajdują się pod literami):
wymowa (kropki, które są zwykle wewnątrz lub powyżej liter):
interpunkcja
Rzeczywiste litery hebrajskie są pokazane w wersji uproszczonej (tj. Końcowy wynik tego, o co tutaj proszono). To, co nazywamy tutaj „akcentem”, znane jest jako znaki diakrytyczne. Artykuł w Wikipedii na temat hebrajskich znaków diakrytycznych zawiera wiele dobrych informacji na temat tych znaków, w tym następujący obraz i podpis:
Rdz 1: 9 I Bóg powiedział: „Niech gromadzą się wody”. Litery czarne, wskazujące na czerwono, cantillation na niebiesko
Przejście od tych podstawowych znaków do tego, co pokazuje pierwsza linia (z samogłosek, itp.), Polega na dodaniu jednego lub więcej „akcentów”. Unicode (UTF-16 w SQL Server, chociaż domyślna interpretacja obsługuje tylko punkty kodowe UCS-2 / Basic Multilingual Plane (BMP)) pozwala niektórym znakom nałożyć inny znak niebędący nakładką, gdy sąsiadują z nimi. Są one znane jako łączenie znaków .
Znaczenie:
SELECT DATALENGTH(N'מַ֖'); -- character taken from original given text
Zwroty:
6
nie 2
tak, jak większość ludzi oczekiwałaby od pojedynczego, dwubajtowego znaku. Może więc staramy się znaleźć jakąś postać, wykonując:
SELECT UNICODE(N'מַ֖');
który zwraca:
1502
Oczywiście funkcje UNICODE
i ASCII
zwracają tylkoINT
wartość pierwszego znaku dowolnego podanego ciągu. Ale wartość 1502 obejmuje tylko 2 bajty, co pozostawia 4 bajty nieuwzględnione. Patrząc na wartości binarne / szesnastkowe tego samego hebrajskiego „znaku”:
SELECT NCHAR(1502), CONVERT(BINARY(2), UNICODE(N'מַ֖')), CONVERT(VARBINARY(10), N'מַ֖');
otrzymujemy:
מ
0x05DE 0xDE05B7059605
Teraz 0x05DE to szesnastkowa reprezentacja 1502, a 1502 to tylko „ מ ”. Kolejną część można podzielić na trzy zestawy 2-bajtowe: DE05 B705 9605 . Teraz wartości ciągów Unicode są przechowywane w Little Endian, co oznacza, że kolejność bajtów jest odwrócona. Jeśli zmienimy każdy z tych trzech zestawów, otrzymamy:
05DE (znak podstawowy) 05B7 0596 (nierozliczone dla 4 bajtów).
Dobrze. Co się stanie, jeśli usuniemy tę podstawową postać?
SELECT REPLACE(N'מַ֖' COLLATE Hebrew_BIN2, NCHAR(1502) COLLATE Hebrew_BIN2, '');
Zwraca dwa pozostałe znaki (nie jest to łatwe do zobaczenia tutaj, więc podałem następujący wiersz jako nagłówek w celu zwiększenia rozmiaru czcionki; możesz również uruchomić powyższe REPLACE
aby je zobaczyć):
Dlatego musimy usunąć każdy pojedynczy punkt kodowy, który jest jednym z tych „dodatkowych” łączących znaków (znalezionych na stronie: http://unicode-table.com/en/search/?q=hebrew ) i to nas opuści z podstawowymi postaciami. Możemy to zrobić poprzez:
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;
Następnie możemy przetestować go z oryginalnym tekstem w następujący sposób:
DECLARE @Hebrew NVARCHAR(200) = N'בְּרֵאשִׁ֖ית בָּרָ֣א אֱלֹהִ֑ים אֵ֥ת הַשָּׁמַ֖יִם וְאֵ֥ת הָאָֽרֶץ';
SELECT dbo.RemoveHebrewAccents(@Hebrew);
Zwroty:
Dodatkowe uwagi:
Technicznie istnieje zestaw punktów kodowych między 64298 a 64334, które mają wbudowane w postać pewne samogłoski i „akcenty” wymowy. Jeśli trzeba je obsłużyć, może to być drugi etap funkcji polegającej na prostej zamianie tych znaków.
Wygląda na to, że te akcenty, znaki interpunkcyjne itp. Punkty kodowe pasują tylko podczas korzystania z sortowania binarnego. Nawet używanie Hebrew_100_CS_AS_KS_WS_SC
nie pasowało do nich. Ale dodaje zadziałały: Hebrew_BIN
, Hebrew_BIN2
, Latin1_General_BIN
, i Latin1_General_BIN2
. W funkcji skończyłem używać Hebrew_BIN2
. Należy pamiętać, że podczas korzystania z zestawień binarnych, chyba że istnieje szczególna potrzeba użycia starszych _BIN
zestawień, należy używać tylko nowych _BIN2
zestawień.
Dla każdego, kto jest ciekawy, hebrajski przykładowy tekst to Bereiszi 1: 1 (jest to również pierwsze słowo po prawej stronie, ponieważ hebrajski jest czytany od prawej do lewej; w języku angielskim będzie to jednak „Księga Rodzaju 1: 1” to nie jest bezpośrednie tłumaczenie tego słowa, tylko nazwa pierwszej księgi Tory / Biblii; bezpośrednie tłumaczenie to „na początku”):
Na początku stworzenia Boga przez niebo i ziemię
2015-01-19: Znalazłem świetne zasoby, które wyjaśniają zarówno łączenie postaci, jak i hebrajski zestaw znaków:
To interesujący problem, z którym kiedyś miałem do czynienia przy pracy z japońskimi postaciami. Uderzyłem w kawałek ceglanego muru, próbując zlokalizować twoje problematyczne postacie, chociaż mam nadzieję, że to pomoże ci gdzieś je znaleźć.
Najpierw umieściłem wszystkie NCHAR w tabeli:
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
Następnie zlokalizowałem jeden z nieakcentowanych znaków:
SELECT c.CharOrder, c.Result
FROM #CHARS AS c
WHERE c.Result = N'ר'
ORDER BY c.CharOrder
Następnie zlokalizowałem zakres znaków, w których znajdują się hebrajskie znaki:
SELECT c.CharOrder, c.Result
FROM #CHARS AS c
WHERE c.CharOrder >= 1488
AND c.CharOrder < 1523
ORDER BY c.CharOrder
Ale próbując znaleźć akcentowane znaki, które chcesz, wydają się nie pojawiać, z wyjątkiem jednego trafienia w kodzie 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
Patrząc na otaczające znaki, nie mogę tak naprawdę zidentyfikować żadnego innego dopasowania do twojego tekstu.
SELECT c.CharOrder, c.Result
FROM #CHARS AS c
WHERE c.CharOrder >= 8499
AND c.CharOrder < 8539
ORDER BY c.CharOrder
Wiele z nich wydaje się rzucanych jak te mgliste małe prostokąty czegokolwiek.
Ponownie przepraszam, że to nie jest rozwiązanie, ale mam nadzieję, że to pomoże.
Użyłem tabeli liczb. Istnieje wiele postów wyjaśniających, co to jest, dlaczego jest to przydatne i jak skutecznie je zdobyć.
Nie używam żadnej wbudowanej funkcji do konwersji znaków akcentowanych na nieakcentowane odpowiedniki. Zamiast tego tworzę listę odnośników, którą wypełnisz wymaganymi konwersjami. Oczywiście będziesz musiał użyć nvarchar
i zdefiniować swoje tłumaczenia N'x'
.
Dzięki temu postowi dla wiersza konkatenacji wiersza.
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;
Ü ö ò ô å Ä Å É ï
. Dlatego standardowa metoda tłumaczenia / mapowania nie będzie działać.
Oto, co zadziałało, jeśli ktoś w przyszłości chce.
function accentHebrewToCleanHebrew($accentHebrew){
//Strip Extras
$search = array("֑", "֒", "֓", "֔", "֕",
"֖", "֗", "֘", "֙", "֚", "֛", "֜",
"֝", "֞", "֟", "֠", "֡", "֢", "֣",
"֤", "֥", "֦", "֧", "֨", "֩", "֪",
"֫", "֬", "֭", "֮", "֯", "ְ", "ֱ",
"ֲ", "ֳ", "ִ", "ֵ", "ֶ", "ַ", "ָ",
"ֹ", "ֺ", "ֻ", "ּ", "ֽ", "־", "ֿ",
"׀", "ׁ", "ׂ", "׃", "ׄ", "ׅ", "׆", "ׇ");
$replace = "";
$cleanHebrew = str_replace($search, $replace, $accentHebrew);
return $cleanHebrew;
}