VBscript.Regexp

Liên hệ QC

hungpecc1

Thành viên gắn bó
Tham gia
24/8/12
Bài viết
1,702
Được thích
2,300
Giới tính
Nam
- Vấn đề xử lý chuỗi ký tự là vấn đề rất hay gặp ( như tìm kiếm, liệt kê, đếm ký tự ......)

- Nếu ta xác định được chính xác vị trí, quy luật ,hoặc các chuỗi tường minh trong chuỗi cần xử lý tức là vấn đề đã được giải quyết 1 phần. Tuy nhiên có những trường hợp ta có thể dễ dàng nhận thấy bằng mắt thường, nhưng để diễn giải nó thì lại khó khăn và phức tạp .
ví dụ như : tìm các số điện thoại trong 1 tin nhắn , liệt kê các địa chỉ email trong văn bản, hay tách các ký tự số từ 1 chuỗi

-Với những trường hợp trên,mình hay thấy các cao thủ sử dụng "VBscript.Regexp" ,Vây regexp là gì , chắc hẳn nhiều bạn cũng muốn tìm hiểu về nó như mình ^^

- Qua quá trình tìm tòi tài liệu từ google và diễn đàn GPE mình xin mạn phép trình những gì mình hiểu về VBscript.Regexp .
Do kiến thức còn hạn chế nên bài viết không tránh khỏi sai sót :

+Mong các cao thủ trong GPE kiểm tra, sửa chữa những sai sót còn tồn tại trong bài viết
+ Bổ sung những thiếu sót để giúp mình hoàn thiện thêm kiến thức ^^

Cụ thể như sau :
RegExp (Regular Expression) :
-Là một biểu thức thường được dùng để mô tả một mẫu chuỗi tuân theo 1 quy luật sắp xếp nào đó (string pattern).
1.Cách khai báo :
PHP:
Set objRegEx = CreateObject("VBScript.RegExp")

2. Các phương thức , tham số và thuộc tính của RegExp
Property Global As Boolean
=True thì RegExp duyệt toàn bộ String, nếu False thì RegExp duyệt có trùng thì dừng
Property IgnoreCase As Boolean
= True so sánh không phân biệt hoa thường , flase thì ngược lại
default là False
Property Pattern As String
Theo cú pháp riêng , đây là phần quan trọng nhất của regExp
Property Multiline As Boolean
=True : Duyệt ở chế độ nhiều dòng
Execute(sourceString As String) As Object
- Tìm chuỗi theo mẫu và trả về một mảng các giá trị tìm thấy
Replace(sourceString As String, replaceString As String) As String
-Thay thế chuỗi bằng chuỗi khác phù hợp với mẫu tìm kiếm.
Test(sourceString As String) As Boolean
-Trả về true nếu như chuỗi gốc khớp với giá trị trả về của biến_regex.Ngược lại là false.
Ngoài ra còn có thêm các phương thức khác như :
Property Count As Long
Property FirstIndex As Long
Property Value
Property Item(index As Long)


Bây giờ mình xin trình bày một vấn đề quan trọng nhất trong RegExp là .Parttern :
Parttern được hiểu như là một mẫu chuỗi thể hiện theo một quy luật nào đó

*Parttern có thể gồm có các ký tự thông thường (Literal Characters) :
Trong RegExp có 11 ký tự mang ý nghĩa đặc biệt: [ \ ^ $ . | ? * + ( ). Chúng dc gọi là các metacharacter., Ngoài các ký tự đặc biệt trên ra, các ký khác được coi là ký tự thông thường :
ví dụ : tách chữ excel trong chuỗi “ Dien dan giai phap excel”
Mã:
Sub Regx()
    Dim str As String, kqua
    str = " Dien dan giai phap excel "
    With CreateObject("VBScript.RegExp")
        .Global = True
        .Pattern = "excel"
        Set kqua = .Execute(str)
        Debug.Print kqua(0) 'Tra ve 1 ket qua duy nhat la excel'
    End With
End Sub
* Các ký tự đặc biệt dùng trong phép toán tìm vị trí :
^: Trả về chuỗi kết quả trong trường hợp chuỗi này nằm ở vị trí đầu của chuỗi gốc
$: Trả về chuỗi kết quả trong trường hợp chuỗi này nằm ở vị trí cuối của chuỗi gốc
\b: Trả về chuỗi kết quả trong trường hợp chuỗi này nằm ở vị trí đầu của một từ trong chuỗi gốc. Nếu cần so sánh ở vị trí cuối từ, hãy đặt biểu thức \b ở vị trí cuối từ.
\B: Trả về chuỗi kết quả trong trường hợp chuỗi này không nằm ở vị trí đầu của một từ trong chuỗi gốc. (tuỳ thuộc vào vị trí đặt \B ở đầu hoặc cuối một từ)
(?=): Trả về chuỗi kết quả nếu theo sau hoặc trước chuỗi đó là một ký tự được chỉ định trước
(?!): Trả về chuỗi kết quả nếu theo sau hoặc trước chuỗi đó không phải là một ký tự được chỉ định trước
ví dụ :
Mã:
Sub timtheo_vitri()
    Dim str As String, kqua
    str = "Lua nep la lua nep lang,lua len lop lop ,long nang lang lang "
    With CreateObject("VBScript.RegExp")
        .Global = True
        .IgnoreCase = True
        .Pattern = "Lua"
            Set kqua = .Execute(str) ' Kqua se tra ve 1 mang gom 3 chu : Lua lua lua
        .Pattern = "^Lua"
            Set kqua = .Execute(str) ' Kqua se tra ve 1 gia tri chu Lua dau tien
    End With
' Tuong tu co the ap dung cho cac truong hop khac ^^
End Sub
* Ta có thể sử dụng các ký tự thông thường ở trong 1 lớp , gọi là lớp ký tự trong RegExp
Lưu ý :
Trong lớp ký tự, các ký tự mang ý nghĩa đặc biệt ( metacharacter)chỉ bao gồm: ] \ ^ - Các metacharacter nói ở phần trước khi đặt trong lớp ký tự sẽ chỉ dc coi như ký tự thông thường
Đặt dấu ^ sau [ trong lớp ký tự sẽ phủ định lớp ký tự đó. Kết quả là lớp ký tự sẽ so khớp với bất kỳ ký tự nào ko nằm trong lớp ký tự đó. Lớp ký tự phủ định có thể so khớp với cả ký tự line break
Để giải phóng các ký tự đặc biệt và sử dụng chúng như ký tự bình thường ta dùng dấu \ để giải phóng chúng
ví dụ pattern = “ 1\+1=2 ‘’ sẽ khớp với chuỗi 1+1 =2 , còn nếu viết “ 1+1=2” nó sẽ khớp với cả 111=2
Cụ thể các lớp như sau :

[xyz]: Tìm một ký tự bất kỳ nằm trong tập ký tự giữa cặp dấu ngoặc vuông
[x-z]: Tìm một ký tự bất kỳ nằm trong tập ký tự từ x đến z
[^xyz]: Tìm một ký tự bất kỳ không thuộc tập ký tự giữa cặp dấu ngoặc vuông.
. : Tìm bất kỳ một ký tự nào không phải là ký tự xuống dòng mới (new line) hoặc ký tự kết thúc dòng (line terminator).
Các ký tự viết tắt ( có thể được dùng ở trong hoặc ở ngoài lớp )
\w: Tìm một ký tự dạng a-Z, 0-9 và dấu gạch dưới.
\W: Ngược lại với \w
\d: Tìm một ký tự thuộc tập ký tự từ 0 đến 9
\D: Ngược lại với \d: Tìm một ký tự không nằm trong tập ký tự từ 0 đến 9
\s: Tìm ký tự " dấu trắng " ( vd : dấu cách , tab ...)
\S:Tìm một ký tự không phải là ký tự " dấu trắng "
ví dụ : tách các chữ số trong 1 chuỗi ( mình sưu tâm của pác Ndu)
Mã:
Function TachSo(Cell As Range) As Double
  Set Temp = CreateObject("VBScript.RegExp")
  Temp.Global = True
  Temp.Pattern = "[^0-9]"
  TachSo = Temp.Replace(Cell, "")
End Function
* Các phép lặp trong regex

RegEx cho phép tìm kiếm lặp bên trong biểu thức:
{x}: Lặp một ký tự hoặc một biểu thức con trước đó x lần
{x,y}: Lặp một ký tự hoặc một biểu thức con trước đó từ x đến y lần
{x,}: Lặp một ký tự hoặc một biểu thức con trước đó >= x lần
?: Lặp một ký tự hoặc một biểu thức con trước đó 0 hoặc 1 lần
*: Lặp một ký tự hoặc một biểu thức con trước đó >=0 lần
+: Lặp một ký tự hoặc một biểu thức con trước đó >=1 lần
Trong RegExp coi ký tự { là ký tự thông thường nên ta không phải giải phóng ký tự đó,
* Gộp nhóm các biểu thức
Chúng ta có thể sử dụng các dấu ngoặc tròn () để gộp nhóm như trong các biểu thức toán học thông thường.

(): Tìm kiếm một nhóm các ký tự bên trong cặp dấu ngoặc và lưu vào chuỗi kết quả.
(?: ): Tìm kiếm chuỗi kết quả không chứa tập ký tự nằm trong cặp dấu ngoặc.
ví dụ :
Mã:
Sub Regx1()
    Dim str As String, kqua
    str = " Messi dang co bong, anh sut bong, vaooooo)"
    With CreateObject("VBScript.RegExp")
        .Global = True
        .Pattern = "[vao]{5}"
        Set kqua = .Execute(str) ' Tra ket qua la chu vaooo
        .IgnoreCase = True
        .Pattern = "[a-z]* +"
        Set kqua = .Execute(str) ' Tach tat ca cac chu cai tu a-z  va dang sau la 1 dau cach
    End With
End sub
Đến đây ta có thể áp dụng RegExp để giải quyết nhiều vấn đề liên quan đến xử lý chuỗi như :

-" Moi thac mac xin gui ve dien dan GPE, dia chi email : xxx@gmail.com,yyy@ yahoo.com.vn " ta có thể dùng RegExp để lấy các địa chỉ mail trong string trên

- hay Kiểm tra dữ liệu nhập vào có là số nguyên dương, số thực không bằng regExp

- Tìm các số điện thoại có 3 số cuối trùng nhau trong các số sau : " 0912.339.777 ; 0983654568 ; 01234.789.999....."

- Tìm các dữ liệu ngày tháng có dang dd/mm/year trong 1 text bất kỳ


- Bây giờ mình xin đề cập đến vấn đề sự làm việc của Regex Engin( mình tham khảo và dịch từ trang http://www.regular-expressions.info/ )

:( hi vọng bài viết của mình có ích cho mọi người , cảm ơn vì đã xem bài viết của mình !

ps :Ấn thanks để động viên tinh thần nhé ^^
 
Lần chỉnh sửa cuối:
?=: Trả về chuỗi kết quả nếu theo sau chuỗi đó là một chuỗi nào đó được chỉ định trước
?!: Trả về chuỗi kết quả nếu sau chuỗi đó không phải là một chuỗi nào đó được chỉ định trước

Không chính xác, có thể gây hiểu lầm cho người khác. Và thiếu.
Vì "?=: Trả về chuỗi kết quả nếu theo sau chuỗi đó là một chuỗi nào đó được chỉ định trước" có nhĩa là "?=: Trả về chuỗi kết quả nếu theo sau chuỗi kết quả đó là một chuỗi nào đó được chỉ định trước"

Xin mời chạy code

[GPECODE=vb]
Sub mytest()
Dim objRe As Object, match As Object, s As String
s = "12345 1678 123 2456 12 ab1289cd"
Set objRe = CreateObject("VBScript.RegExp")
objRe.Global = True
objRe.pattern = "(?=12)\d+"
For Each match In objRe.Execute(s)
Debug.Print match.Value
Next
End Sub
[/GPECODE]

Có 4 "chuỗi kết quả" là

12345
123
12
1289

Sau mỗi "chuỗi kết quả đó" không có chuỗi "12" nào.
Tôi cố tình xét trường hợp mà bạn thiếu.

Không chính xác vì trong pattern có thể có nhiều "đoạn" dạng (?=mẫu) vậy thì đk để xét xem 1 đoạn cụ thể trong chuỗi nguồn có khớp với pattern là gì? Là sau nó phải có "chuỗi chỉ định trước" của (?=mẫu) thứ mấy? Thứ nhất, thứ hai, ...?

Lưu ý tương tự cho (?!mẫu)
--------------
Mà không có cái gọi là ?= và ?! mà chỉ có (?=mẫu) và (?!mẫu) - ngoặc đơn là bắt buộc

\s: Tìm ký tự cách (dấu cách)

Thực ra khái niệm "dấu cách" là ký tự " ". Nên chăng dùng khái niệm "dấu trắng"? Tức "dấu cách", TAB, CR, LF ..., hoặc viết hẳn ra \s = [ \f\n\r\t\v]
 
Lần chỉnh sửa cuối:
Upvote 0
Cảm ơn hai anh/bạn đã trình bày rất cụ thể, chi tiết về VBscript.Regexp (một công cụ hay nhưng còn rất mơ hồ với mình).

Mình có ý kiến: Bạn hungpecc1 nghiên cứu góp ý của anh siwtom và hiệu chỉnh lại bài #1 để anh em đọc thông suốt hơn. Bài viết của bạn rất hay.
 
Upvote 0
Cảm ơn pác Siwtom nhiều , :) , pác diễn đạt rất dễ hiểu và ví dụ rất tường minh
Mình cũng thêm 1 ví dụ nữa cho các bạn dễ hiểu thêm về cách dùng ( ?=)
[GPECODE=vb]
Sub mytest1()Dim objRe As Object, match As Object, s As String
s = "Thu 2 la ngay dau tuan , thu 3 la ngay dau tuan"
Set objRe = CreateObject("VBScript.RegExp")
objRe.Global = True
objRe.IgnoreCase = True
objRe.Pattern = "th(?=u)"
For Each match In objRe.Execute(s)
Debug.Print match.Value
Next
' Ket qua tra ve Th va th vi theo sau la Th la chu u
End Sub


[/GPECODE]
 
Lần chỉnh sửa cuối:
Upvote 0
Phải chi topic này nằm chung với topic REGEXP đã và đang thảo luận thì thuận tiện hơn.
 
Upvote 0
Có cách nào gộp 2 đề tài vào làm 1 không ? để dễ theo dõi và thảo luận nhj

Mình nghĩ không cần thiết lắm đâu.
Topic này cho ta cái nhìn tổng quan, cơ bản còn cái kia đi phân tích từng tình huống cụ thể. Ai mới bước vào VBscript.Regexp nên đọc topic này trước mới hiểu được vấn đề.
Nếu cần minh họa thì mình Links cho nhau.
 
Upvote 0
Minh đang dùng Office 2016 for mac nên không biết làm sao để gọi VBscript.Regexp
 
Upvote 0
Web KT
Back
Top Bottom