71
Chương 2: Thao tác dữ liệu
|
Ngăn cách các biểu thứcthể so trùng, dụ
AAA|ABA|ABB
sẽ so trùng với
AAA
,
ABA
, hoặc
ABB
(các biểu thức được so trùng từ trái sang).
[abc]
So trùng với một trong các ký tự trong nhóm, ví dụ
[AbC]
sẽ so trùng với
A
,
b
, hoặc
C
.
[^abc]
So trùng với bất cứ tự nào không thuộc các tự trong nhóm, dụ
[^AbC]
sẽ không so trùng với
A
,
b
, or
C
nhưng so trùng với
B
,
F
,…
[a-z]
So trùng với bất kỳ ký tự nào thuộc khoảng này, ví dụ
[A-C]
sẽ so trùng với
A
,
B
, hoặc
C
.
( )
Xác định một biểu thức con sao cho được xem như một yếu tố đơn lẻ
đối với các yếu tố được trình bày trong bảng này.
?
Xác định có một hoặc không có ký tự hoặc biểu thức con đứng trước nó, ví
dụ
A?B
so trùng với
B
,
AB
, nhưng không so trùng với
AAB
.
*
Xác định không hoặc nhiềutự hoặc biểu thức con đứng trước nó,
ví dụ
A*B
so trùng với
B
,
AB
,
AAB
,
AAAB
,…
+
Xác định một hoặc có nhiều tự hoặc biểu thức con đứng trước nó,
dụ
A+B
so trùng với
AB
,
AAB
,
AAAB
,… nhưng không so trùng với
B
.
{n}
Xác định có đúng
n
ký tự hoặc biểu thức con đứng trước nó, ví dụ
A{2}
chỉ
so trùng với
AA
.
{n,}
Xác định ít nhất
n
thoặc biểu thức con đứng trước nó, dụ
A{2,}
so trùng với
AA
,
AAA
,
AAAA
,… nhưng không so trùng với
A
.
{n, m}
Xác định từ
n
đến
m
tự đứng trước nó, dụ
A{2,4}
so trùng với
AA
,
AAA
, và
AAAA
nhưng không so trùng với
A
hoặc
AAAAA
.
Khi dữ liệu cần kiểm tra càng phức tạp thì pháp của biểu thức chính quy cũng càng phức
tạp. dụ, dễ dàng kiểm tra dữ liệu nhập chỉ chứa số hay chiều dài tối thiểu, nhưng kiểm
tra một URL khá phức tạp. Bảng 2.3 liệt một số biểu thức chính quy dùng để kiểm tra các
kiểu dữ liệu thông dụng.
Bảng 2.3
Một số biểu thức chính quy thông dụng
Kiểu dữ liệu nhập Mô tả Biểu thức chính quy
Số Chỉ chứa các chữ số thập phân; ví dụ
5
, hoặc
5683874674
.
^\d+$
PIN Chứa 4 chữ số thập phân,
ví dụ
1234
.
^\d{4}$
Mật khẩu đơn giản Chứa từ 6 đến 8 ký tự; ví dụ
ghtd6f
hoặc
b8c7hogh
.
^\w{6,8}$
Số thẻ tín dụng
Chứa dữ liệu phù hợp với cấu trúc
của hầu hết các loại số thẻ tín dụng,
ví dụ
4921835221552042
hoặc
4921-
8352-2155-2042
.
^\d{4}-?\d{4}-?\d{4}- ?
\d{4}$
72
Chương 2: Thao tác dữ liệu
Địa chỉ e-mail
[\w-]+
nghĩa là chứa một
hoặc nhiều ký tự word
hoặc dấu gạch ngang, ví dụ
some-body@adatum.com
^[\w-]+@([\w- ]
+\.)+[\w-]+$
HTTP hoặc HTTPS
URL
Dữ liệu là một URL dựa-trên-HTTP
hay dựa-trên-HTTPS, ví dụ
http://www.microsoft.com
^https?://([\w- ]
+\.)+[\w-]+(/[\w- ./ ?
%=]*)?$
Một khi đã biết pháp của biểu thức chính quy, bạn tạo một đối tượng
System.Text.RegularExpression.Regex
bằng cách truyền cho phương thức khởi dựng của
chuỗi chứa biểu thức chính quy. Sau đó, gọi phương thức
IsMatch
của đối tượng
Regex
truyền chuỗi cần kiểm tra, phương thức này trả về một giá trị luận lý cho biết chuỗi có hợp lệ
không. pháp của biểu thức chính quy sẽ chỉ định
Regex
so trùng toàn bộ chuỗi hay chỉ so
trùng một phần của chuỗi (xem
^
,
\A
,
$
, và
\z
trong bảng 2.2)
Phương thức
ValidateInput
dưới đây minh họa cách kiểm tra chuỗi nhập bằng biểu thức
chính quy:
public static bool ValidateInput(string regex, string input) {
// Tạo đối tượng Regex dựa trên biểu thức chính quy.
Regex r = new Regex(regex);
// Kiểm tra dữ liệu nhập có trùng với biểu thức chính quy hay không.
return r.IsMatch(input);
}
Bạn thể sử dụng đối tượng
Regex
để kiểm tra nhiều chuỗi, nhưng không thể thay đổi biểu
thức chính quy được gắn cho nó; bạn phải tạo một đối tượng
Regex
mới tương ứng với một
cấu trúc mới. Phương thức
ValidateInput
ở trên tạo ra một đối tượng
Regex
mới mỗi lần được
gọi, thay vào đó bạn có thể sử dụng phương thức tĩnh nạp chồng
IsMatch
.
public static bool ValidateInput(string regex, string input) {
// Kiểm tra dữ liệu nhập có trùng với biểu thức chính quy hay không.
return Regex.IsMatch(input, regex);
}
6.
6. S d ng bi u th c chính quy đã đ c biên d ch ượ
S d ng bi u th c chính quy đã đ c biên d ch ượ
Bạn cần giảm thiểu các tác động lên hiệu năng của ứng dụng khi các biểu thức
chính quy phức tạp được sử dụng thường xuyên.
73
Chương 2: Thao tác dữ liệu
Khi khởi tạo đối tượng
System.Text.RegularExpressions.Regex
, hãy truyền thêm
tùy chọn
Compiled
thuộc kiểu liệt
System.Text.RegularExpressions.
RegexOptions
để biên dịch biểu thức chính quy thành
Microsoft Intermediate
Language
(
MSIL
).
Theo mặc định, khi bạn tạo đối tượng
Regex
, mẫu biểu thức chính quy do bạn xác định trong
phương thức khởi dựng được biên dịch thành một dạng trung gian (không phải MSIL). Mỗi
lần bạn sử dụng đối tượng
Regex
, bộ thực thi phiên dịch dạng trung gian này và áp dụng nó để
kiểm tra chuỗi. Với các biểu thức chính quy phức tạp được sử dụng thường xuyên, việc phiên
dịch lặp lặp đi lại có thể gây tác động xấu lên hiệu năng của ứng dụng.
Khi tùy chọn
RegexOptions.Compiled
được chỉ định, bộ thực thi sẽ biên dịch biểu thức chính
quy thành MSIL. MSIL này được gọi just-in-time (JIT), được biên dịch thành máy
nguyên sinh trong lần thực thi đầu tiên, giống như assembly thông thường. Biểu thức
chính quy được biên dịch cũng được sử dụng giống như đối tượng
Regex
, việc biên dịch chỉ
giúp thực thi nhanh hơn.
Tuy nhiên, việc biên dịch biểu thức chính quy cũng có vài nhược điểm. Trước tiên, trình biên
dịch JIT phải làm việc nhiều hơn, dẫn đến chậm quá trình biên dịch, đặc biệt khi tạo biểu thức
chính quy được biên dịch khi ứng dụng khởi động. Thứ hai, biểu thức chính quy được biên
dịch vẫn tồn tại trong bộ nhớ khi không còn được sử dụng nữa, không bị bộ thu gom rác
(Garbage Collector) xóa đi như các biểu thức chính quy thông thường. Vùng nhớ bị chiếm chỉ
được giải phóng khi chương trình kết thúc, hoặc khi bạn giải phóng miền ứng dụng.
Dòng mã sau minh họa cách tạo một đối tượng
Regex
được biên dịch thành MSIL:
Regex reg = new Regex(@"[\w-]+@([\w-]+\.)+[\w-]+",
RegexOptions.Compiled);
Ngoài ra, phương thức tĩnh
Regex.CompileToAssembly
cho phép bạn tạo một biểu thức chính
quy được biên dịch ghi vào một assembly khác. Nghĩa bạn thể tạo một assembly
chứa các biểu thức chính quy để sử dụng cho nhiều ứng dụng sau này. Để biên dịch một biểu
thức chính quy và lưu nó vào một assembly, thực hiện các bước sau:
1. Tạo một mảng
System.Text.RegularExpressions.RegexCompilationInfo
đủ lớn để
chứa các đối tượng
RegexCompilationInfo
, mỗi đối tượng ứng với một biểu thức chính
quy cần được biên dịch.
2. Tạo một đối tượng
RegexCompilationInfo
cho mỗi biểu thức chính quy và truyền đối số
cho phương thức khởi dựng để xác định các thuộc tính của biểu thức chính quy này.
Các thuộc tính thông dụng là:
IsPublic
giá trị
bool
xác định lớp biểu thức chính quy được tạo ra tầm vực
là công khai hay không.
Name
một
String
xác định tên của lớp.
Namespace
một
String
xác định không gian tên của lớp.
Pattern
một
String
xác định mẫu mà biểu thức chính quy sẽ so trùng (xem chi
tiết ở mục 2.5).
Options
một giá trị thuộc kiểu liệt
System.Text.RegularExpressions.
RegexOptions
xác định các tùy chọn cho biểu thức chính quy.
74
Chương 2: Thao tác dữ liệu
3. Tạo một đối tượng
System.Reflection.AssemblyName
để xác định tên của assembly mà
phương thức
Regex.CompileToAssembly
sẽ tạo ra.
4. Gọi phương thức
Regex.CompileToAssembly
, truyền các đối số mảng
RegexCompilationInfo
và đối tượng
AssemblyName
.
Quá trình trên tạo ra một assembly chứa các khai báo lớp cho từng biểu thức chính quy được
biên dịch, mỗi lớp dẫn xuất từ
Regex
. Để sử dụng một biểu thức chính quy đã được biên dịch
trong assembly, bạn cần tạo đối tượng biểu thức chính quy này và gọi các phương thức của nó
giống n khi tạo với phương thức khởi dựng
Regex
bình thường. Bạn nhớ thêm tham
chiếu tới assembly khi sử dụng các lớp biểu thức chính quy nằm trong nó.
Đoạn mã sau minh họa cách tạo một assembly có tên là MyRegex.dll, chứa hai biểu thức chính
quy có tên là
PinRegex
CreditCardRegex
:
using System.Text.RegularExpressions;
using System.Reflection;
public class CompiledRegexExample {
public static void Main() {
// Tạo mảng chứa các đối tượng RegexCompilationInfo.
RegexCompilationInfo[] regexInfo = new RegexCompilationInfo[2];
// Tạo đối tượng RegexCompilationInfo cho PinRegex.
regexInfo[0] = new RegexCompilationInfo(@"^\d{4}$",
RegexOptions.Compiled, "PinRegex", "", true);
// Tạo đối tượng RegexCompilationInfo cho CreditCardRegex.
regexInfo[1] = new RegexCompilationInfo(
@"^\d{4}-?\d{4}-?\d{4}-?\d{4}$",
RegexOptions.Compiled, "CreditCardRegex", "", true);
// Tạo đối tượng AssemblyName để định nghĩa assembly.
AssemblyName assembly = new AssemblyName();
assembly.Name = "MyRegEx";
// Tạo các biểu thức chính quy được biên dịch.
Regex.CompileToAssembly(regexInfo, assembly);
75
Chương 2: Thao tác dữ liệu
}
}
7.
7. T o ngày và gi t chu i
T o ngày và gi t chu i
Bạn cần tạo một thể hiện
System.DateTime
tả giờ, ngày được chỉ định trong
một chuỗi.
Sử dụng phương thức
Parse
hoặc
ParseExact
của lớp
DateTime
.
Có nhiều cách mô tả ngày, giờ; ví dụ 1st June 2004, 1/6/2004, 6/1/2004, 1-Jun-2004 cùng chỉ
một ngày; 16:43 4:43 PM cùng chỉ một giờ. Lớp
DateTime
cung cấp phương thức tĩnh
Parse
rất linh hoạt, cho phép tạo thể hiện
DateTime
từ nhiều cách tả khác nhau trong
chuỗi.
Phương thức
Parse
rất mạnh trong việc tạo đối tượng
DateTime
từ một chuỗi cho trước. Nó có
thể xử lý một chuỗi chỉ chứa một phần thông tin hay chứa thông tin sai, và thay thế các giá trị
thiếu bằng các giá trị mặc định. Ngày mặc định ngày hiện tại, giờ mặc định 12:00:00
AM. Nếu sau mọi cố gắng,
Parse
không thể tạo đối tượng
DateTime
, sẽ ném ngoại lệ
System.FormatException
. Ví dụ sau minh họa tính linh hoạt của
Parse
:
// 01/09/2004 12:00:00 AM
DateTime dt1 = DateTime.Parse("Sep 2004");
// 05/09/2004 02:15:33 PM
DateTime dt2 = DateTime.Parse("Sun 5 September 2004 14:15:33");
// 05/09/2004 12:00:00 AM
DateTime dt3 = DateTime.Parse("5,9,04");
// 05/09/2004 02:15:33 PM
DateTime dt4 = DateTime.Parse("5/9/2004 14:15:33");
// 07/10/2004 02:15:00 PM (giả sử ngày hiện tại là 07/10/2004)
DateTime dt5 = DateTime.Parse("2:15 PM");
Phương thức
Parse
linh hoạtcó thể tự sửa lỗi. Tuy nhiên, mức độ linh hoạt này không cần
thiết trong trường hợp bạn muốn bảo đảm các chuỗi phải theo một định dạng nhất định. Khi
đó, sử dụng phương thức
ParseExact
thay cho
Parse
. Dạng đơn giản nhất của
ParseExact
nhận ba đối số: chuỗi chứa ngày giờ, chuỗi định dạng xác định cấu trúc chuỗi chứa ngày
giờ phải tuân theo, và một tham chiếu
IFormatProvider
cung cấp thông tin đặc thù về bản địa.
Nếu
IFormatProvider
null
, thông tin về bản địa của tiểu trình (thread) hiện hành sẽ được
sử dụng.
Nếu ngày giờ trong chuỗi đang xét không đúng với định dạng quy định,
ParseExact
sẽ ném
ngoại lệ
System.FormatException
. Chuỗi định dạng được sử dụng tương tự như khi bạn chỉ