Asked Jul 22nd, 4:12 PM 168 0 1
  • 168 0 1
0

Hỏi về check regex tiếng việt

Share
  • 168 0 1

Cho mình hỏi là mình muốn check đoạn text tiếng việt sau bằng regex. Mình muốn nó bắt vào 'MU' nhưng nó đang bắt vào 'mu' của từ 'muốn'. Vậy nguyên nhân là do sao ạ?

let test = 'muốn học tập MU';
const regexp = new RegExp(/\bmu\b/, 'i'); // showing how to pass optional flags
console.log(test.match(regexp)); // > Array ["mu"]

Nhưng nếu sửa 'muốn' thành 'mueốn' thì ok:

let test = 'mueốn học tập MU';
const regexp = new RegExp(/\bmu\b/, 'i'); // showing how to pass optional flags
console.log(test.match(regexp));  // > Array ["MU"]

1 ANSWERS


Answered Jul 23rd, 3:10 AM
Accepted
+2

\b xác định vị trí đầu chuỗi, cuối chuỗi hoặc giữa 2 kí tự 1 là word character (\w), 2 là non-word character (\W) Và vì các kí tự tiếng việt (ê, ô, ế...), không phải là word character (có thể test bằng \w) nên trường hợp của 'muốn' đúng với pattern \bmu\b (\b thứ nhất là đầu chuỗi, \b thứ hai là giữa 1 word và non-word)

Share
Jul 23rd, 4:26 AM

vậy ở trong đoạn text ‘muốn học tập MU' mình muốn nó bắt vào ‘MU’ thì viết regex như nào nhỉ bạn?

0
| Reply
Share
Jul 23rd, 4:54 AM

@bacode Bạn có thể dùng cú pháp lookaround để tìm (không phải phiên bản nào cũng hỗ trợ. Như google dùng RE2, không hỗ trợ) Tìm tất cả các chuỗi MU, mà không đứng sau hoặc đứng trước bất kì kí tự gì ngoài whitespace

let test = 'MU muốn học tậpMU MU';
let regexp = new RegExp(/(?<![^\s])mu(?![^\s])/, 'ig'); // showing how to pass optional flags
console.log(test.match(regexp)); // > Array ["MU", "MU]
0
| Reply
Share
Jul 23rd, 7:02 PM

@Sorrow chrome với safari trên iphone không được hỗ trợ à bạn?

0
| Reply
Share
Jul 24th, 2:30 AM

@bacode Mình đang nói đến các loại engine (library) của regular expression (Regex). Regex trên thực tế là các thư viện được các ngôn ngữ lập trình sử dụng, do đó, mỗi một thư viện lại cung cấp 1 bộ cú pháp khác nhau. Có những cú pháp chung, phổ biến thì thư viện nào cũng hỗ trợ. Có những cái như cú pháp lookaround mình dùng bên trên, lại không được hỗ trợ 100%.

Javascript dùng thư viện XRegExp, hỗ trợ positive và negative lookaround, chạy trên Internet Explorer 5.5+, Firefox 1.5+, Chrome, Safari 3+, and Opera 11+ Nguồn: http://xregexp.com/

Các bộ g suite của Google như google sheet (hàm regexmatch(), regexextract() ) lại dùng thư viện là RE2. Thư viện này hỗ trợ kém và thiếu nhiều cú pháp như lookaround chẳng hạn Nguồn: https://github.com/google/re2

Tham khảo thêm: https://en.wikipedia.org/wiki/Comparison_of_regular-expression_engines

0
| Reply
Share
Jul 24th, 3:39 AM

@Sorrow Mình đang làm trên reactjs. Thì dùng lib XRegExp này ok k bạn?

0
| Reply
Share
Jul 24th, 4:02 AM

@bacode Từ ES2018 thì JS hỗ trợ lookahead, lookbehind rồi nên không cần dùng lib ngoài vẫn có thể giải được bài toán của bạn nhé (Kể cả với reactjs)

Nguồn: https://en.wikipedia.org/wiki/Comparison_of_regular-expression_engines#Part_1

0
| Reply
Share
Jul 24th, 5:57 AM

@Sorrow đoạn mình cần check sẽ implement như nào nhỉ bạn?

0
| Reply
Share
Jul 25th, 2:43 AM

@bacode Mình có viết 1 ví dụ ở trên rồi đó

0
| Reply
Share
Jul 26th, 1:31 AM

@Sorrow mình thử đoạn này của bạn chạy ok. nhưng nó ko hỗ trợ trên safari. Cả chrome, safari trên iphone nữa

let test = 'MU muốn học tậpMU MU'; let regexp = new RegExp(/(?<![^\s])mu(?![^\s])/, 'ig'); // showing how to pass optional flags console.log(test.match(regexp)); // > Array ["MU", "MU]

0
| Reply
Share
Jul 27th, 1:37 AM

@bacode Bạn thử lại đoạn này xem nhé

let test = 'MU muốn học tậpMU MU';
let regexp = new RegExp(/\bmu\b(?![\u00C0-\u1EF3])/, 'ig'); // Bắt tất cả các chuỗi "mu" mà không theo sau bởi 1 kí tự latin extend (kí tự tiếng việt)
console.log(test.match(regexp)); // > Array ["MU", "MU]
0
| Reply
Share
Jul 27th, 4:08 PM

@Sorrow Sao nó không bắt được Đà Nẵng nhỉ bạn?

let test = 'Đà Nẵng muốn học tậpMU MU';
let regexp = new RegExp(/\bĐà Nẵng\b(?![\u00C0-\u1EF3])/, 'ig');
console.log(test.match(regexp)); // > null
0
| Reply
Share
Jul 28th, 1:14 AM

@bacode Như mình đã nói, \b xác định vị trí giữa 1 word và non-word. Và 'Đ' là một non-word, trước đó lại không có 1 word nào cả, nên pattern không hoạt động được.

Thêm 1 word bất kì vào trước 'Đ', hoặc bỏ anchor \b ban đầu đi thì code chạy.

let test = 'aĐà Nẵng muốn học tậpMU MU';
let regexp = new RegExp(/\bĐà Nẵng\b(?![\u00C0-\u1EF3])/, 'ig');
console.log(test.match(regexp)); // > 'Đà Nẵng
let test = 'Đà Nẵng muốn học tậpMU MU';
let regexp = new RegExp(/Đà Nẵng\b(?![\u00C0-\u1EF3])/, 'ig');
console.log(test.match(regexp)); // > 'Đà Nẵng
0
| Reply
Share
Jul 28th, 2:01 AM

@Sorrow vậy mình muốn cái text mình truyền vào là động có thể lúc là Đà Nẵng lúc là MU thì có cách nào check đc cho cả 2 trường hợp ko nhỉ bạn?

0
| Reply
Share
Jul 28th, 7:41 AM

@bacode Bạn muốn có 1 lời giải chung cho một bài toán thì cũng hơi phức tạp nhỉ.

Theo mình nghĩ, nếu cụm từ bạn cần bắt nó là 1 từ có nhiều chữ cái, từ có 2 tiếng trở lên, thì bạn có thể search thằng từ đó /string/ mà không sợ nó bị lẫn do ghép vần.

Còn nếu chuỗi bạn cần bắt nó là 1 cụm kí tự, dễ bị lẫn vào các từ khi ghép vần (như mu bị lẫn vào muốn, uống lẫn vào xuống), thì bạn có thể dùng các pattern mình có nêu ở trên.

Vì bản chất việc chúng ta cố làm nãy giờ là bắt 1 chuỗi đứng riêng không bị lẫn vào các từ khác (do ghép vần) nhở.

0
| Reply
Share
Jul 28th, 10:08 AM

@Sorrow ý bạn là sẽ dùng if else để check r chọn regex phù hợp à?

0
| Reply
Share