Các hàm PHP để thao tác với chuỗi tiếng Việt (v1.2)

Phần này tôi sẽ xây dựng các hàm để thao tác sâu hơn với chuỗi tiếng Việt nói chung, và họ tên người Việt nói riêng. Cái này sẽ sử dụng các function độc lập trước đó là:

Mã đầy đủ (phần giải thích cho từng hàm có dưới mã đầy đủ):

<?php 
/* 
 * PHP functions to process Vietnamese strings v1.2
 * MIT License
 * Nguyen Duc Anh - freehost.page
 */



////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////



function vn_rmv_wsp($str) { // bỏ khoảng trắng dư thừa
    $str2 = trim($str, ' '); // bỏ khoảng trắng trước và sau chuỗi
    $rs = preg_replace('/\s+/', ' ', $str2); // loại bỏ khoảng trắng thừa trong chuỗi

return $rs;
}



////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////



function vn_low_rmv($str) { // loại bỏ khoảng trắng, chuyển sang ký tự thường 
    $str2 = vn_rmv_wsp($str); // bỏ khoảng trắng trước và sau chuỗi
    $rs = mb_strtolower($str2,'UTF-8'); // chuyển thành ký tự thường
    
return $rs;
}



////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////



// áp dụng được cho một từ hoặc chuỗi nhiều từ
function vn_num_char($str) { // số lượng ký tự của chuỗi, một từ hay chuỗi nhiều từ đều được
    $str2 = pop_hex_convert($str); // chuyển về dạng mã hóa hex tiêu chuẩn
    $rs = mb_strlen($str2, 'UTF-8');

return $rs;
} 



////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////



// áp dụng được cho một từ hoặc chuỗi nhiều từ
function vn_remove_accents($str){ // xóa dấu của một ký tự hoặc một từ, hoặc chuỗi
    $timbre = vna_hex_timbre(); // mã hóa hex của dấu tiếng Việt
    $hex = bin2hex(rarely_hex_convert($str)); // chuyển sang mã hex để tìm dấu
    
    foreach ($timbre as $tim) { // tách thành các dấu
             $pt='/'.$tim.'/'; // tạo mẫu
                  if (preg_match($pt, $hex)) { //so khớp
                      $hex = preg_replace($pt,'',$hex); // khử dấu của $hex; nó vẫn đang ở dạng hex
                  } 
    }
    
    $rs = pop_hex_convert(hex2bin($hex)); // chuyển về từ mã hóa phổ thông
    if ($rs == "") {$rs = $str;} // dự phòng
    
return $rs;
}



////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////



// áp dụng được cho một từ hoặc chuỗi nhiều từ
// được thiết kế hướng đến một từ
function vn_num_acc_char($str) { // tìm số lượng ký tự có dấu trong một từ
    $rs = 0; // rs có thể lớn hơn 1, những từ đơn có hơn một dấu sẽ được xem là lỗi chính tả
    $acc = vna_acc_char_array(); // lấy mảng các nguyên âm đơn có dấu
    $strx = pop_hex_convert($str); // chuyển về dạng mã hóa phổ biến, và chuyển về ký tự thường
           foreach ($acc as $acc_char) {
               $pt='/'.$acc_char.'/'; 
               if (preg_match_all($pt, $strx)) {$rs += preg_match_all($pt, $strx);}
           }
           
return $rs;           
}



////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////



// áp dụng được cho một từ hoặc chuỗi nhiều từ
// được thiết kế hướng đến một từ
function vn_num_none_acc_vowel($str) { // tìm số lượng các nguyên âm đơn không dấu trong một từ
    $rs = 0;
    $none_acc_vowel = vna_vowel_lett(); // các nguyên âm đơn không dấu mã hóa phổ thông
    $strx = pop_hex_convert($str); // chuyển về dạng mã hóa phổ biến, và chuyển về ký tự thường
           foreach ($none_acc_vowel as $nav) {
               $pt = '/'.$nav.'/';
               if (preg_match_all($pt, $strx)) {$rs += preg_match_all($pt, $strx);}
           }
           
return $rs; // trả về số lượng các nguyên âm đơn không dấu 
}




/////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////



// áp dụng được với một từ, cũng như một chuỗi nhiều từ
function vn_foreign_check_low($str) { // trả về 1 nếu có ký tự nước ngoài, trả về 0 nếu không có
    $rs=0;
    $fr = array("f","j","w","z"); // tìm các ký tự nước ngoài, bình thường không có trong tiếng Việt
    $hex = pop_hex_convert($str); // chuyển về dạng viết thường, mã hóa phổ biến
    foreach ($fr as $fr2) {
        $pt = '/'.$fr2.'/';
        $r = preg_match($pt, $hex);
        if ($r > 0) {$rs=1; break;} // chỉ cần có một ký tự nước ngoài là đủ để tên không phải là dạng thuần Việt    
    }
    
return $rs;    
}


/////////////////////////////////////////////////////////////////////// End code

1. Loại bỏ khoảng trắng dư thừa trước, sau một từ

function vn_rmv_wsp($str) { // bỏ khoảng trắng dư thừa
    $str2 = trim($str, ' '); // bỏ khoảng trắng trước và sau chuỗi
    $rs = preg_replace('/\s+/', ' ', $str2); // loại bỏ khoảng trắng thừa trong chuỗi

return $rs;
}

Hai hàm cơ bản được dùng là:

  • trim dùng để loại bỏ khoảng trắng trước và sau chuỗi;
  • preg_replace để tìm 2 khoảng trắng trở lên và thay thế nó bằng một khoảng trắng tiêu chuẩn;

Việc loại bỏ khoảng trắng dư thừa giúp việc tách từ, đếm số lượng ký tự được chính xác.

Ví dụ:

$str = " Nguyễn   Đức Anh";
echo vn_rmv_wsp($str);

// kết quả: Nguyễn Đức Anh

2. Loại bỏ khoảng trắng và chuyển chuỗi về ký tự thường

function vn_low_rmv($str) { // loại bỏ khoảng trắng, chuyển sang ký tự thường 
    $str2 = vn_rmv_wsp($str); // bỏ khoảng trắng trước và sau chuỗi
    $rs = mb_strtolower($str2,'UTF-8'); // chuyển thành ký tự thường
    
return $rs;
}
  • Trước tiên loại bỏ khoảng trắng dư thừa;
  • Sau đó dùng hàm có sẵn của PHP là mb_strtolower để chuyển nó thành ký tự thường;

Họ tên chuẩn sẽ viết hoa đầu từ, nhưng để tiện thao tác với chuỗi, chúng ta sẽ chuyển nó về dạng viết thường.

Ví dụ:

$str = " Nguyễn   Đức Anh";
echo vn_low_rmv($str);

// kết quả: nguyễn đức anh

3. Đếm số lượng ký tự của một từ

Áp dụng được cho một từ hoặc chuỗi nhiều từ. Trong trường hợp chuỗi nhiều từ thì nó tính cả khoảng trống trong chuỗi giữa các từ.

// áp dụng được cho một từ hoặc chuỗi nhiều từ
function vn_num_char($str) { // số lượng ký tự của chuỗi, một từ hay chuỗi nhiều từ đều được
    $str2 = pop_hex_convert($str); // chuyển về dạng mã hóa hex tiêu chuẩn
    $rs = mb_strlen($str2, 'UTF-8');

return $rs;
}

4. Xóa dấu của một ký tự hoặc một từ

Có thể áp dụng được với một từ hoặc chuỗi nhiều từ. Nhưng được viết với mục đích áp dụng cho một từ.

// áp dụng được cho một từ hoặc chuỗi nhiều từ
function vn_remove_accents($str){ // xóa dấu của một ký tự hoặc một từ, hoặc chuỗi
    $timbre = vna_hex_timbre(); // mã hóa hex của dấu tiếng Việt
    $hex = bin2hex(rarely_hex_convert($str)); // chuyển sang mã hex để tìm dấu
    
    foreach ($timbre as $tim) { // tách thành các dấu
             $pt='/'.$tim.'/'; // tạo mẫu
                  if (preg_match($pt, $hex)) { //so khớp
                      $hex = preg_replace($pt,'',$hex); // khử dấu của $hex; nó vẫn đang ở dạng hex
                  } 
    }
    
    $rs = pop_hex_convert(hex2bin($hex)); // chuyển về từ mã hóa phổ thông
    if ($rs == "") {$rs = $str;} // dự phòng
    
return $rs;
}

5. Tìm số lượng nguyên âm có dấu trong một từ

Có thể áp dụng được với một từ hoặc chuỗi nhiều từ. Nhưng được viết với mục đích áp dụng cho một từ.

// áp dụng được cho một từ hoặc chuỗi nhiều từ
// được thiết kế hướng đến một từ
function vn_num_acc_char($str) { // tìm số lượng ký tự có dấu trong một từ
    $rs = 0; // rs có thể lớn hơn 1, những từ đơn có hơn một dấu sẽ được xem là lỗi chính tả
    $acc = vna_acc_char_array(); // lấy mảng các nguyên âm đơn có dấu
    $strx = pop_hex_convert($str); // chuyển về dạng mã hóa phổ biến, và chuyển về ký tự thường
           foreach ($acc as $acc_char) {
               $pt='/'.$acc_char.'/'; 
               if (preg_match_all($pt, $strx)) {$rs += preg_match_all($pt, $strx);}
           }
           
return $rs;           
}

Sử dụng hàm preg_match_all để đếm số lượng ký tự được tìm thấy thay vì preg_match, nó sẽ giúp tránh trường hợp đếm thiếu khi có 2 nguyên âm giống nhau trong từ.


6. Tìm số lượng các nguyên âm đơn (1 ký tự) không dấu trong một từ

Có thể áp dụng được với một từ hoặc chuỗi nhiều từ. Nhưng được viết với mục đích áp dụng cho một từ.

// áp dụng được cho một từ hoặc chuỗi nhiều từ
// được thiết kế hướng đến một từ
function vn_num_none_acc_vowel($str) { // tìm số lượng các nguyên âm đơn không dấu trong một từ
    $rs = 0;
    $none_acc_vowel = vna_vowel_lett(); // các nguyên âm đơn không dấu mã hóa phổ thông
    $strx = pop_hex_convert($str); // chuyển về dạng mã hóa phổ biến, và chuyển về ký tự thường
           foreach ($none_acc_vowel as $nav) {
               $pt = '/'.$nav.'/';
               if (preg_match_all($pt, $strx)) {$rs += preg_match_all($pt, $strx);}
           }
           
return $rs; // trả về số lượng các nguyên âm đơn không dấu 
}

Sử dụng hàm preg_match_all để đếm số lượng ký tự được tìm thấy thay vì preg_match, nó sẽ giúp tránh trường hợp đếm thiếu khi có 2 nguyên âm giống nhau trong từ.


7. Kiểm tra xem từ có ký tự nước ngoài hay không

Áp dụng được với một từ, cũng như một chuỗi nhiều từ.

// áp dụng được với một từ, cũng như một chuỗi nhiều từ
function vn_foreign_check_low($str) { // trả về 1 nếu có ký tự nước ngoài, trả về 0 nếu không có
    $rs=0;
    $fr = array("f","j","w","z"); // tìm các ký tự nước ngoài, bình thường không có trong tiếng Việt
    $hex = pop_hex_convert($str); // chuyển về dạng viết thường, mã hóa phổ biến
    foreach ($fr as $fr2) {
        $pt = '/'.$fr2.'/';
        $r = preg_match($pt, $hex);
        if ($r > 0) {$rs=1; break;} // chỉ cần có một ký tự nước ngoài là đủ để tên không phải là dạng thuần Việt    
    }
    
return $rs;    
}