Home > Quản trị Linux > Thủ thuật Linux > Giải thích cú pháp Regular Expression trong Linux

Giải thích cú pháp Regular Expression trong Linux

Trong bài này mình sẽ hướng dẫn các bạn cách sử dụng Regular Expression trong Linux, đây là một phần kiến thức nâng cao khi học Linux, nhưng nếu áp dụng được thì bạn sẽ thấy nó cực kỳ hữu dụng khi áp dụng cùng với những câu lệnh như sed, awk,...

Trước tiên bạn cần tìm hiểu một chút về khái niệm Regular Expression trong Linux là gì đã nhé.

I. Regular Expression trong Linux là gì?

Regular expression là biểu thức chính quy giúp bạn xử lý chuỗi trong một file. Hãy thử tưởng tượng xem có những lúc bạn phải validate form email chẳng hạn, hay bạn muốn cut, copy, paste hay replace chuỗi trong một file nào đó thì đã có

Regular expression hay viết tắt RegEx một ngôn ngữ xử lý chuỗi rất mạnh.

RegEx không phải ngôn ngữ lập trình, nó chỉ một tập hợp các cú pháp dùng để bắt chuỗi. Nhưng nó cực kỳ phổ biến và hầu hết những ngôn ngữ lập trình nào phổ biến đều hỗ trợ hết.

Vì bài này mang tính chất thực hành nên các bạn cũng mình tìm hiểu RegEx thông qua một vài ví dụ sau nhé.

Mình thường sử dụng trang https://regex101.com/ để thực hành. Giao diện như sau:

regex linux 1 jpg

II. Cú pháp Regular Expression trong Linux

Việc đầu tiên của mình học các cú pháp đơn giản nhất của RegEx:

  • [abc] Tìm và so sánh đoạn chuỗi nào đó xem có từ nào trùng khớp với một ký tự trong ngoặc vuông . Ví dụ [abc] sẽ trùng khớp với từ a hoặc từ b hoặc từ c
  • [0123456789] Sẽ trùng khớp với bất cứ số nào trong khoảng từ 0 đến 9. Hay có thể viết tắt là [0-9] cũng như vậy
  • [a-z] Sẽ trùng khớp với bất cứ ký tự nào trong bảng chữ cái không viết hoa và không ký tự đặc biệt.
  • [^abc] Mũ ở trong ngoặc vuông đơn giản chỉ là phủ định lại. Ví dụ [^abc] nghĩa là nó sẽ khớp với ký tự không phải a hoặc là ký tự b hoặc là ký tự c
  • [^a-z] Cũng tương tự như vậy. Nó sẽ ngược lại với [a-z] với nghĩa là nó sẽ trùng khớp với bất cứ ký tự nào không phải trong bảng chữ cái viết thường và ký tự đặc biệt.
  • \s Trùng khớp với ký tự là khoảng trắng bao gồm cả khi bạn dùng tab
  • \S Thì ngược lại với \s, trùng với ký tự không phải không không phải là khoảng cách ( Non whitespace )
  • \w Trùng khớp với ký tự là chữ cái và bao gồm cả dấu _ ( underscore )
  • \W Thì lại ngược lại với \w, trùng khớp với các ký tự đặc biệt không bao gồm _ ( underscore)
  • \b Trùng khớp với toàn bộ chữ cái đứng trước nó. Ví dụ Ha\b sẽ trùng với từ Ha trong đoạn Ha Noi is beautiful. Nhưng sẽ không trùng khớp với HaNoi is beautiful.
  • \B Thì ngược lại với \b, trùng khớp với một phần ký tự đứng trước nó. Ví dụ: Ha\B sẽ trùng khớp với đoạn HaNoi is beautiful, nhưng không trùng khớp với đoạn Ha Noi is beautiful.
  • \d Trùng khớp với một số bất kỳ như 12345…
  • \D thì ngược lại với \d, chữ cái viết hoa viết thường, ký tự đặc biệt và bao gồm cả khoảng cách.
  • a|b Trùng khớp với ký tự a hoặc ký tự b. Ví dụ Ha|Noi sẽ trùng khớp với chữ Ha hoặc chữ Noi
  • . Trùng khớp với một ký tự đơn bất kỳ nhưng không có ký tự có dấu hoặc dấu ngắt dòng. Ví dụ . sẽ trùng với ký tự a ký tự b chứ không trùng với ký tự á, ắ hay ấ và dấu ngắt dòng.
  • * Trùng khớp với ký tự đứng trước nó. Ví dụ \d* sẽ trùng khớp với chuỗi các số

Mới chỉ là căn bản thôi mà đã nhức đầu phải không nào. Nhưng không sao chúng ta vào ví dụ sẽ dễ hiểu thêm nhiều nhé.

III. Một vài ví dụ thực hành trước khi áp dụng lệnh Linux

1. Tìm các chuỗi là dạng số:

/\b\d+\b/

regex linux 2 jpg

Trong \d+ nghĩa là tìm tất cả các chuỗi ký tự có số, \b đấu cuối nghĩa là bắt đầu chuỗi phài là số và kết thúc chuỗi cũng là số.

2. Tìm ngày tháng

/\b\d{1,2}\/\d{1,2}\/(\d{4}|d{2})\b/

regex linux 3 jpg

Mình phân tích nhé:

  • \d{1,2} nghĩa là chuỗi đầu tiên gồm một số hoặc hai số
  • \ nghĩa là ký tự escape, bạn hiểu đơn giản là / là ký tự đóng nếu muốn RegEx hiểu rằng nó không phải là điểm cuối của mã RegEx thì cần thêm ký tự \
  • (d{4}|d{2}) nghĩa là chuỗi cuối cùng của mình là chuỗi gồm 4 số hoặc là 2 số
  • \b ở đầu cuối nghĩa là không có số nào đứng trước đứng sau ngoài mã tìm ngày tháng năm mà mình tạo ra.

3. Tìm chính xác ngày tháng năm

Như bạn đã thấy mình nếu mình để là 60/60/2020 thì nó vẫn tìm ra rằng đó là ngày tháng năm, nhưng như thế rõ ràng là sai rồi, đúng không? Vậy mình cần nâng cấp mã RegEx của mình ngay.

/\b(0?[1-9]|[12]\d|3[01])[\/\-.](0?[1-9]|(1[012]))[\/\-.](\d{2}|\d{4})\b/

regex linux 4 jpg

Nhìn hoa mắt đấy nhỉ, nhưng không sao chúng ta cùng phân tích từng đoạn một nhé:

  • \b như mình đã phân tích từ 2 bài trước nên mình sẽ k nhắc tới nữa.
  • Trong đoạn này ta lại chia thành 3 đoạn nhỏ (0?[1-9]|[12]\d|3[01])
  • 0?[1-9] nghĩa là bắt đầu là 0 hoặc là không phải là số gì cả và số thứ 2 thì bắt đầu bằng là số bất kỳ từ 1 đến 9. Đoạn này có thể bắt được ký tự số như là 03 hay số 3 riêng lẻ.
  • | nghĩa là hoặc là
  • [12]\d nghĩa là đoạn sau bắt đầu bằng 1 hoặc 2 và số tiếp theo là số bất kỳ. Đoạn này giúp ta bắt được các ngày như 12, 19, 21, 25 nhưng không bắt được các số bắt đầu bằng số 3 trở đi.
  • 3[01] nghĩa là bắt đầu bằng số 3, số tiếp theo có thể là số 0 hoặc là số 1. Có thể bắt được các số như 30 và 31

Ta phân tích đoạn tiếp theo

  • [\/\-.] nghĩa là có thể là / hoặc là - hoặc là . , giữa ký tự / ta có 2 ký tự escape để hiểu rằng đoạn này là mã RegEx của mình chưa hết, và mình còn viết tiếp. Dùng để tìm thấy dấu / trong 20/1/2020 hoặc tìm thấy ký tự - trong 20-1-2020 hoặc là tìm thấy thấy . trong 20.1.2020

Ta vừa phân tích xong đoạn RegEx về ngày. Đoạn tháng và năm thì cũng tương tự vậy nên để tránh dài dòng mình không viết nữa. Nếu bạn nào không hiểu có thể comment, mình sẽ cố gắng giải thích cho bạn hiểu

3. Bắt một chuỗi ký tự ở nhiều dòng bất kỳ

Ví dụ : Biểu thức RegEx sau có thể bắt được nhiều dòng như sau

/<h1>[\s\S]*<h2>/

regex linux 5 jpg

Trong đó:

  • \s nghĩa lấy được dấu cách
  • \S nghĩa là lấy được tất cả các chữ cái ngoài dấu cách.
  • [\s\S] Kết hợp lại ta nhận thấy sẽ lấy được tất cả các ký tự bao gồm cả khoảng cách hay xuống dòng.
  • * nghĩa là nhân bản lên nhiều lần, giúp ta tìm được chuỗi dài vô tận

Tổng kết: Thật sự lúc đầu động vào RegEx thật sự là khá nhức đầu nhưng khi bạn động vào lâu rồi đấy thì bạn có thể cảm thấy rất hay, thú vị và đương nhiên là vẫn còn nhức đầu rồi.

Như bạn biết đấy bạn muốn giỏi về RegEx trong Linux thì bắt buộc phải làm nhiều, hãy tiếp tục thực hành thật nhiều để master món này nhé. Khá là hữu ích cho công việc lập trình sau này của bạn đó.

Xem thêm

BÀI VIẾT

notice png LIST home png HOME hot gif BÁO
LỖI
top png TOP