Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regular Expression to accept all Thai characters and English letters in python

Tags:

python

regex

thai

I need to vectorize text documents in Thai (e.g Bag of Words, doc2vec).

First I want to go over each document, omitting everything except the Thai characters and English words (e.g. no punctuation, no numbers, no other special characters except apostrophe).

For English documents, I use this regular expression: [^a-zA-Z' ]|^'|'$|''

For Thai documents, I cannot find the right regular expression to use. I know that the Unicode block for Thai is u0E00–u0E7F. I tried [^ก-๛a-zA-Z' ]|^'|'$|'' and many other combinations but they don't succeed.

For example: I want

"ทรูวิชั่นส์ ประกาศถ่ายทอดสดศึกฟุตบอล พรีเมียร์ ลีก อังกฤษ ครบทุกนัดเป็นเวลา 3 ปี ตั้งแต่ฤดูกาล 2016/2017 - 2018/2019 พร้อมด้วยอีก 5 ลีกดัง อาทิ ลา ลีกา สเปน, กัลโช เซเรีย เอ อิตาลี และลีกเอิง ฝรั่งเศส ภายใต้แพ็กเกจสุดคุ้ม ทั้งผ่านมือถือ และโทรทัศน์ some, English words here! abc123"

to be:

"ทรูวิชั่นส์ ประกาศถ่ายทอดสดศึกฟุตบอล พรีเมียร์ ลีก อังกฤษ ครบทุกนัดเป็นเวลา ปี ตั้งแต่ฤดูกาล พร้อมด้วยอีก ลีกดัง อาทิ ลา ลีกา สเปน, กัลโช เซเรีย เอ อิตาลี และลีกเอิง ฝรั่งเศส ภายใต้แพ็กเกจสุดคุ้ม ทั้งผ่านมือถือ และโทรทัศน์ some English words here abc"

like image 579
Shani Shalgi Avatar asked Jul 27 '16 14:07

Shani Shalgi


4 Answers

I'll be using some lists to do what I need.

First, let's create the pattern :

pattern = re.compile(r"[^\u0E00-\u0E7Fa-zA-Z' ]|^'|'$|''")

I'll use a string named test_string, containing your example :

test_string="ทรูวิชั่นส์ ประกาศถ่ายทอดสดศึกฟุตบอล พรีเมียร์ ลีก อังกฤษ ครบทุกนัดเป็นเวลา 3 ปี ตั้งแต่ฤดูกาล 2016/2017 - 2018/2019 พร้อมด้วยอีก 5 ลีกดัง อาทิ ลา ลีกา สเปน, กัลโช เซเรีย เอ อิตาลี และลีกเอิง ฝรั่งเศส ภายใต้แพ็กเกจสุดคุ้ม ทั้งผ่านมือถือ และโทรทัศน์ some, English words here! abc123"

First, let's get the characters to remove, in a list :

char_to_remove = re.findall(pattern, test_string)

Then, let's create a list made of the character from our original string, without these characters :

list_with_char_removed = [char for char in test_string if not char in char_to_remove]

We transform this list into a string, and we're done.

result_string = ''.join(list_with_char_removed)

Result is :

'ทรูวิชั่นส์ ประกาศถ่ายทอดสดศึกฟุตบอล พรีเมียร์ ลีก อังกฤษ ครบทุกนัดเป็นเวลา ปี ตั้งแต่ฤดูกาล พร้อมด้วยอีก ลีกดัง อาทิ ลา ลีกา สเปน กัลโช เซเรีย เอ อิตาลี และลีกเอิง ฝรั่งเศส ภายใต้แพ็กเกจสุดคุ้ม ทั้งผ่านมือถือ และโทรทัศน์ some English words here abc'

If you have any cleaner way to do any of the steps/any questions, do not hesitate !

like image 152
HolyDanna Avatar answered Oct 23 '22 13:10

HolyDanna


In Python 3,

s = "ทรูวิชั่นส์ ประกาศถ่ายทอดสดศึกฟุตบอล พรีเมียร์ ลีก อังกฤษ ครบทุกนัดเป็นเวลา 3 ปี ตั้งแต่ฤดูกาล 2016/2017 - 2018/2019 พร้อมด้วยอีก 5 ลีกดัง อาทิ ลา ลีกา สเปน, กัลโช เซเรีย เอ อิตาลี และลีกเอิง ฝรั่งเศส ภายใต้แพ็กเกจสุดคุ้ม ทั้งผ่านมือถือ และโทรทัศน์ some, English words here! abc123"
pattern = re.compile(r"(?:[^\d\W]+)|\s")
for each in pattern.findall(s): print(each, end="")

Outputs this:

ทรวชนส ประกาศถายทอดสดศกฟตบอล พรเมยร ลก องกฤษ ครบทกนดเปนเวลา  ป ตงแตฤดกาล    พรอมดวยอก  ลกดง อาท ลา ลกา สเปน กลโช เซเรย เอ อตาล และลกเอง ฝรงเศส ภายใตแพกเกจสดคม ทงผานมอถอ และโทรทศน some English words here

Accents are being removed, so this is not a perfect answer. I'm currently looking around to see why this is happening.

EDIT: Using the character range from HolyDanna's answer, you can keep the accents. Interesting that just using word does not keep accents (this is probably due to how unicode code points add accents as another code point after the accented character, but seems like a bug). It also has the side effect of removing characters from other languages. Just replace the compile line HolyDanna's:

pattern = re.compile(r"[\u0E00-\u0E7Fa-zA-Z' ]")

You can get rid of the apostrophe (etc) if you don't want it.

like image 45
Keozon Avatar answered Oct 23 '22 11:10

Keozon


Sadly, there are not many regular expression libraries with good Unicode support, and Python's re library is one of them. Oniguruma has proper Unicode support and I believe it has Python bindings, and Perl's built-in regular expressions have good Unicode support.

I normally don't suggest that people switch languages, but in this case, you will save a lot of trouble by using Perl (and for the record, I have the gold Python badge, and haven't touched Perl in the past decade!). Here is a taste of how simple it is (it should be the same in Oniguruma, which again, I think has Python bindings):

[^\p{Latin}\p{Thai}]+

Here is Perl example code:

#!/usr/bin/perl -w
use utf8;
$_ = "ทรูวิชั่นส์ ประ...abc123";
s/[^\p{Latin}\p{Thai}]+/ /g;
print;
print "\n";

Here is the output:

ทรูวิชั่นส์ ประกาศถ่ายทอดสดศึกฟุตบอล พรีเมียร์ ลีก อังกฤษ ครบทุกนัดเป็นเวลา ปี ตั้งแต่ฤดูกาล พร้อมด้วยอีก ลีกดัง อาทิ ลา ลีกา สเปน กัลโช เซเรีย เอ อิตาลี และลีกเอิง ฝรั่งเศส ภายใต้แพ็กเกจสุดคุ้ม ทั้งผ่านมือถือ และโทรทัศน์ some English words here abc

like image 1
Dietrich Epp Avatar answered Oct 23 '22 11:10

Dietrich Epp


In Java you can match a combination of Thai en English with: ^[\\p{L}\\p{javaUnicodeIdentifierPart}\\p{Blank}\\p{P}]*$

Breakdown:

  • \\p{L} is an 'normal' letter
  • \\p{javaUnicodeIdentifierPart} matches a Thai letter
  • \\p{Blank} matches a space character
  • \\p{P} matches punctuation.

I'm not an expert in the Thai language (other than that I recognize it), but without the punctuation-match the string does not match.

like image 1
Sven Avatar answered Oct 23 '22 12:10

Sven