2016-04-16 19 views
5

Mam ciąg znaków, który zawiera zarówno zdania w języku arabskim, jak i angielskim. To, czego chcę, to wydobywać tylko zdania w języku arabskim.Jak pobierać tylko teksty arabskie z ciągu za pomocą wyrażeń regularnych?

my_string=""" 
What is the reason 
ذَلِكَ الْكِتَابُ لَا رَيْبَ فِيهِ هُدًى لِلْمُتَّقِينَ 
behind this? 
ذَلِكَ الْكِتَابُ لَا رَيْبَ فِيهِ هُدًى لِلْمُتَّقِينَ 
""" 

This Link pokazuje, że zakres Unicode literami arabskimi jest 0600-06FF.

Tak, bardzo podstawowe próba przyszła mi do głowy to:

import re 
print re.findall(r'[\u0600-\u06FF]+',my_string) 

Ale to nie zdało, gdyż zwraca następującą listę.

['What', 'is', 'the', 'reason', 'behind', 'this?'] 

Jak widać, jest dokładnie naprzeciwko tego, co chcę. Czego tu mi brakuje?

N.B.

wiem, że można dopasować arabskie litery za pomocą dopasowania odwrotny jak poniżej:

print re.findall(r'[^a-zA-Z\s0-9]+',my_string) 

Ale ja tego nie chcę.

Odpowiedz

4

Możesz użyć re.sub, aby zastąpić znaki ASCIS pustym łańcuchem.

>>> my_string=""" 
... What is the reason 
... ذَلِكَ الْكِتَابُ لَا رَيْبَ فِيهِ هُدًى لِلْمُتَّقِينَ 
... behind this? 
... ذَلِكَ الْكِتَابُ لَا رَيْبَ فِيهِ هُدًى لِلْمُتَّقِينَ 
... """ 
>>> print(re.sub(r'[a-zA-Z?]', '', my_string).strip()) 
ذَلِكَ الْكِتَابُ لَا رَيْبَ فِيهِ هُدًى لِلْمُتَّقِينَ 

ذَلِكَ الْكِتَابُ لَا رَيْبَ فِيهِ هُدًى لِلْمُتَّقِينَ 

Twój regex nie działa, ponieważ używasz Python 2 i ciąg jest str trzeba konwertować my_string Unicode go do pracy. Jednak to nie działa idealnie na Python3.x

>>> print "".join(re.findall(ur'[\u0600-\u06FF]', unicode(my_string, "utf-8"), re.UNICODE)) 
ذَلِكَالْكِتَابُلَارَيْبَفِيهِهُدًىلِلْمُتَّقِينَذَلِكَالْكِتَابُلَارَيْبَفِيهِهُدًىلِلْمُتَّقِينَ 
+0

Dzięki za miłą odpowiedź, +1 Ale dlaczego powyższa próba nie działa? –

+0

Jestem zadowolona :) Dziękuję –

2

Twój oryginalny kod był prawidłowy, po prostu potrzebne do kodowania my_string z prawidłowym kodowaniu „utf-8” i dodać u w swojej strukturze re od pracy z python2,

>>> for x in re.findall(ur'[\u0600-\u06FF]+', my_string.decode('utf-8')): 
     print x 


ذَلِكَ 
الْكِتَابُ 
لَا 
رَيْبَ 
فِيهِ 
هُدًى 
لِلْمُتَّقِينَ 
ذَلِكَ 
الْكِتَابُ 
لَا 
رَيْبَ 
فِيهِ 
هُدًى 
لِلْمُتَّقِينَ 

To daje listę dopasowanych napisów unicode zamiast pojedynczych znaków, które nie muszą połączyć je z powrotem ''.join

Jeśli były w Python3, nie zrobić n EED któregokolwiek z kodowaniem tweeking domyślnym kodowaniem jest 'UTF-8':

>>> for x in re.findall(r'[\u0600-\u06FF]+', my_string): 
     print(x) 


ذَلِكَ 
الْكِتَابُ 
لَا 
رَيْبَ 
فِيهِ 
هُدًى 
لِلْمُتَّقِينَ 
ذَلِكَ 
الْكِتَابُ 
لَا 
رَيْبَ 
فِيهِ 
هُدًى 
لِلْمُتَّقِينَ 
2

Kod jest:

print re.findall(r'[\u0600-\u06FF]+',my_string) 

Podczas dopasowywania sekwencji bajtów, nie ma takiego pojęcia jak Unicode punktów kodowych. Dlatego sekwencje specjalne w wyrażeniu regularnym nie mają żadnego sensu. Nie są interpretowane tak, jak myślałeś, ale po prostu oznaczają u.

więc podczas analizowania wyrażenie regularne dla bajtów, jest równoznaczne z:

print re.findall(r'[u0600-u06FF]+',my_string) 

Klasa ta postać jest interpretowane jako „jednego z u060 lub bajt w zakresie 0-u lub jeden z 06FF”. To z kolei jest równoważne z [0-u], ponieważ wszystkie inne bajty są już zawarte w tym zakresie.

print re.findall(r'[0-u]+', my_string) 

Demonstracja:

my_string = "What is thizz?" 
print re.findall(r'[\u0600-\u06FF]+',my_string) 
['What', 'is', 'thi', '?'] 

Zauważ, że zz nie pasuje, ponieważ chodzi za u w zestawie znaków ASCII.

+0

To jest najlepsze wytłumaczenie sytuacji. Chciałbym móc zrobić +2. Dzięki kolego :) –

+1

nie powinno brzmieć: "jeden z ** u060 ** lub bajt w zakresie * 0-u * lub jeden z * 06FF *" – sweaver2112

+0

Dziękuję bardzo za staranne czytanie. Naprawiłem to. –