Học Biểu thức Thông thường với khóa học miễn phí này

“Một số người, khi đối mặt với một vấn đề, nghĩ rằng 'Tôi biết, tôi sẽ sử dụng cụm từ thông dụng.' Bây giờ họ có hai vấn đề." -Jamie Zawinski

Đối với một số người, việc sử dụng cụm từ thông dụng có thể là một vấn đề. Nhưng nó không phải là một vấn đề đối với bạn. Bài viết này là một khóa học đầy đủ về Biểu thức chính quy.

1. Giới thiệu

Biểu thức chính quy, hoặc chỉ RegEx, được sử dụng trong hầu hết các ngôn ngữ lập trình để xác định một mẫu tìm kiếm có thể được sử dụng để tìm kiếm những thứ trong một chuỗi.

Tôi đã phát triển một khóa học video đầy đủ, miễn phí trên Scrimba.com để dạy những điều cơ bản về biểu thức chính quy.

Bài viết này chứa khóa học ở dạng viết. Nhưng nếu bạn muốn xem phiên bản video với các bài học tương tác, bạn có thể xem trên Scrimba. Các phần trong bài viết này tương ứng với các phần trong khóa học Scimba.

Khóa học này cùng với chương trình giảng dạy của RegEx tại freeCodeCamp.org. Bạn có thể kiểm tra điều đó để biết các thử thách mã hóa và để kiếm chứng chỉ.

Những bài học này tập trung vào việc sử dụng RegEx trong JavaScript, nhưng các nguyên tắc áp dụng trong nhiều ngôn ngữ lập trình khác mà bạn có thể chọn sử dụng. Nếu bạn chưa biết JavaScript cơ bản, có thể hữu ích nếu bạn trình bày một chút về nó trước. Tôi cũng có một khóa học JavaScript cơ bản mà bạn có thể truy cập trên Scrimba và trên kênh YouTube freeCodeCamp.org.

Vậy hãy bắt đầu! Bạn sẽ tiết kiệm thời gian trong ngày. ?

2. Sử dụng Phương pháp Kiểm tra

Để khớp các phần của chuỗi bằng RegEx, chúng tôi cần tạo các mẫu giúp bạn thực hiện việc khớp đó. Chúng ta có thể chỉ ra rằng một cái gì đó là một mẫu RegEx bằng cách đặt mẫu giữa các dấu gạch chéo /, như vậy /pattern-we-want-to-match/.

Hãy xem một ví dụ:

// We want to check the following sentencelet sentence = "The dog chased the cat."
// and this is the pattern we want to match.let regex = /the/

Lưu ý cách chúng tôi sử dụng /the/để chỉ ra rằng chúng tôi đang tìm kiếm "cái" trong của chúng tôi sentence.

Chúng ta có thể sử dụng test()phương thức RegEx để biết một mẫu có trong một chuỗi hay không.

// String we want to testlet myString = "Hello, World!";
// Pattern we want to findlet myRegex = /Hello/;
// result is now truelet result = myRegex.test(myString);

3. Khớp các chuỗi chữ

Bây giờ chúng ta hãy tìm Waldo.

let waldoIsHiding = "Somewhere Waldo is hiding in this text.";let waldoRegex = /Waldo/;
// test() returns true, so result is now also truelet result = waldoRegex.test(waldoIsHiding);

Lưu ý rằng trong ví dụ waldoRegexnày phân biệt /waldo/chữ hoa chữ thường , vì vậy nếu chúng ta viết với chữ thường 'w', thì chúng ta resultsẽ là false.

4. Khớp một chuỗi chữ với các khả năng khác nhau

RegEx cũng có ORtoán tử là |ký tự.

let petString = "James has a pet cat.";
// We can now try to find if either of the words are in the sentencelet petRegex = /dog|cat|bird|fish/;
let result = petRegex.test(petString);

5. Bỏ qua trường hợp trong khi khớp

Cho đến nay, chúng tôi đã xem xét các mẫu khi trường hợp của các chữ cái quan trọng. Làm cách nào chúng ta có thể làm cho các mẫu RegEx của mình không phân biệt chữ hoa chữ thường?

Để bỏ qua trường hợp, chúng ta có thể làm điều đó bằng cách thêm icờ vào cuối một mẫu, như vậy /some-pattern/i.

let myString = "freeCodeCamp";
// We ignore case by using 'i' flaglet fccRegex = /freecodecamp/i;
// result is truelet result = fccRegex.test(myString);

6. Trích xuất các trận đấu

Khi chúng ta muốn trích xuất giá trị phù hợp, chúng ta có thể sử dụng match()phương thức.

let extractStr = "Extract the word 'coding' from this string.";
let codingRegex = /coding/;
let result = extractStr.match(codingRegex);
console.log(result);
// Terminal will show: // > ["coding"]

7. Tìm nhiều hơn so với trận đấu đầu tiên

Bây giờ khi chúng ta biết cách trích xuất một giá trị và cũng có thể trích xuất nhiều giá trị bằng cách sử dụng gcờ

let testStr = "Repeat, Repeat, Repeat";
let ourRegex = /Repeat/g;
testStr.match(ourRegex); // returns ["Repeat", "Repeat", "Repeat"]

Chúng tôi cũng có thể kết hợp gcờ với icờ, để trích xuất nhiều trận đấu và bỏ qua cách viết hoa.

let twinkleStar = "Twinkle, twinkle, little star";
let starRegex = /twinkle/ig;// writing /twinkle/gi would have the same result.
let result = twinkleStar.match(starRegex);
console.log(result);
// Terminal will show: // > ["Twinkle", "twinkle"]

8. Khớp mọi thứ với Dấu chấm ký tự đại diện

Trong RegEx .là một ký tự đại diện có thể khớp với bất kỳ thứ gì.

let humStr = "I'll hum a song";
let hugStr = "Bear hug";
// Looks for anything with 3 characters beginning with 'hu'let huRegex = /hu./;
humStr.match(huRegex); // Returns ["hum"]
hugStr.match(huRegex); // Returns ["hug"]

9. Khớp một ký tự với nhiều khả năng

So khớp bất kỳ ký tự nào là tốt, nhưng nếu chúng ta muốn giới hạn đối sánh với một nhóm ký tự được xác định trước thì sao? Chúng tôi có thể làm bằng cách sử dụng []bên trong RegEx của chúng tôi.

Nếu chúng ta có /b[aiu]g/, có nghĩa là chúng ta có thể ghép "bag", "big" và "bug".

Nếu chúng ta muốn trích xuất tất cả các nguyên âm từ một câu, đây là cách chúng ta có thể thực hiện bằng RegEx.

let quoteSample = "Beware of bugs in the above code; I have only proved it correct, not tried it.";
let vowelRegex = /[aeiou]/ig;
let result = quoteSample.match(vowelRegex);

10. Khớp các chữ cái trong bảng chữ cái

Nhưng nếu chúng ta muốn ghép một loạt các chữ cái thì sao? Chắc chắn, hãy làm điều đó.

let quoteSample = "The quick brown fox jumps over the lazy dog.";
// We can match all the letters from 'a' to 'z', ignoring casing. let alphabetRegex = /[a-z]/ig;
let result = quoteSample.match(alphabetRegex);

11. Khớp các số và chữ cái trong bảng chữ cái

Chữ cái thì tốt, nhưng nếu chúng ta cũng muốn có số thì sao?

let quoteSample = "Blueberry 3.141592653s are delicious.";
// match numbers between 2 and 6 (both inclusive), // and letters between 'h' and 's'. let myRegex = /[2-6h-s]/ig;
let result = quoteSample.match(myRegex);

12. Khớp các ký tự đơn không được chỉ định

Đôi khi, việc chỉ định các ký tự mà bạn không muốn xem dễ dàng hơn. Chúng được gọi là 'Ký tự được phân bổ' và trong RegEx bạn có thể làm điều đó bằng cách sử dụng ^.

let quoteSample = "3 blind mice.";
// Match everything that is not a number or a vowel. let myRegex = /[^0-9aeiou]/ig;
let result = quoteSample.match(myRegex);// Returns [" ", "b", "l", "n", "d", " ", "m", "c", "."]

13. Ghép các ký tự xuất hiện một hoặc nhiều lần

Nếu bạn muốn khớp một ký tự xuất hiện một hoặc nhiều lần, bạn có thể sử dụng +.

let difficultSpelling = "Mississippi";
let myRegex = /s+/g;
let result = difficultSpelling.match(myRegex);// Returns ["ss", "ss"]

14. Ghép các ký tự xuất hiện từ 0 trở lên

Ngoài ra còn có một bộ *định lượng RegEx. Điều này phù hợp với thậm chí 0 lần xuất hiện của một ký tự. Tại sao điều này có thể hữu ích? Hầu hết thời gian nó thường kết hợp với các ký tự khác. Hãy xem một ví dụ.

let soccerWord = "gooooooooal!";
let gPhrase = "gut feeling";
let oPhrase = "over the moon";
// We are trying to match 'g', 'go', 'goo', 'gooo' and so on. let goRegex = /go*/;
soccerWord.match(goRegex); // Returns ["goooooooo"]
gPhrase.match(goRegex); // Returns ["g"]
oPhrase.match(goRegex); // Returns null

15. Tìm các nhân vật với Lazy Matching

Đôi khi các trận đấu theo mẫu của bạn có thể có nhiều hơn một kết quả. Ví dụ: giả sử tôi đang tìm một mẫu trong một từ titanicvà các giá trị phù hợp của tôi phải bắt đầu bằng chữ 't' và kết thúc bằng chữ 'i'. Kết quả có thể có của tôi là 'titani' và 'ti'.

Đây là lý do tại sao RegEx có các khái niệm về 'Trận đấu tham lam' và 'Trận đấu lười biếng'.

Trận tham lam tìm thấy những trận đấu dài nhất có thể của chuỗi đó phù hợp mô hình RegEx, đây là một trận đấu RegEx mặc định:

let string = "titanic";
let regex = /t[a-z]*i/;
string.match(regex);// Returns ["titani"]

Lazy trận đấu thấy các trận đấu ngắn nhất có thể của chuỗi đó phù hợp mô hình RegEx và sử dụng nó, chúng ta cần phải sử dụng ?:

let string = "titanic";
let regex = /t[a-z]*?i/;
string.match(regex);// Returns ["ti"]

16. Tìm một hoặc nhiều tội phạm trong một cuộc săn

Bây giờ chúng ta hãy xem xét một thử thách RegEx. Chúng ta cần tìm tất cả những tên tội phạm ('C') trong một đám đông. Chúng tôi biết rằng chúng luôn ở cùng nhau và bạn cần phải viết một RegEx để tìm chúng.

let crowd = 'P1P2P3P4P5P6CCCP7P8P9';
let reCriminals = /./; // Change this line
let matchedCriminals = crowd.match(reCriminals);

Bạn có thể tìm thấy tôi xem qua giải pháp trong diễn viên Scrimba này.

17. Khớp các mẫu chuỗi bắt đầu

RegEx cũng cho phép bạn so khớp các mẫu chỉ ở phần đầu của một chuỗi. Chúng ta đã nói về ^việc tạo một tập hợp phủ định. Chúng ta có thể sử dụng cùng một ký hiệu để tìm một kết quả phù hợp chỉ ở phần đầu của một chuỗi.

let calAndRicky = "Cal and Ricky both like racing.";
// Match 'Cal' only if it's at the beginning of a string. let calRegex = /^Cal/;
let result = calRegex.test(calAndRicky); // Returns true
let rickyAndCal = "Ricky and Cal both like racing.";
let result = calRegex.test(rickyAndCal); // Returns false

18. Đối sánh các mẫu chuỗi kết thúc

Điều gì về việc kết hợp một mẫu ở cuối một chuỗi? Chúng tôi có thể sử dụng $cho điều đó.

let caboose = "The last car on a train is the caboose";
// Match 'caboose' if it's at the end of a string.let lastRegex = /caboose$/;
let result = lastRegex.test(caboose); // Returns true

19. Khớp tất cả các chữ cái và số

Trước đó trong phần 10 và 11, tôi đã chỉ cho bạn cách chúng ta có thể ghép các dãy chữ cái và số. Nếu tôi yêu cầu bạn viết một RegEx khớp với tất cả các chữ cái và số và bỏ qua các trường hợp của chúng, bạn có thể đã viết một cái gì đó như thế /[a-z0-9]/givà điều đó chính xác. Nhưng nó hơi dài.

RegEx có một cái gì đó được gọi là 'Các lớp ký tự tốc ký' , về cơ bản là một cách viết tắt cho biểu thức RegEx thông thường. Để khớp tất cả các chữ cái và số, chúng tôi có thể sử dụng \wvà chúng tôi cũng nhận được gạch dưới _phù hợp như một phần thưởng.

let quoteSample = "The five boxing wizards jump quickly.";
// Same as /[a-z0-9_]/gi to match a-z (ignore case), 0-9 and _let alphabetRegexV2 = /\w/g;
// The length of all the characters in a string// excluding spaces and the period. let result = quoteSample.match(alphabetRegexV2).length;
// Returns 31

20. Khớp mọi thứ trừ các chữ cái và con số

Nếu chúng ta muốn làm ngược lại và đối sánh mọi thứ không phải là chữ cái hoặc số (cũng loại trừ dấu gạch dưới _), chúng ta có thể sử dụng\W

let quoteSample = "The five boxing wizards jump quickly.";
// Match spaces and the periodlet nonAlphabetRegex = /\W/g;
let result = quoteSample.match(nonAlphabetRegex).length;
// Returns 6

21. Khớp tất cả các số

Ok, nếu bạn chỉ muốn số thì sao? Có một lớp ký tự viết tắt cho điều đó không? Chắc chắn rồi \d.

let numString = "Your sandwich will be $5.00";
// Match all the numberslet numRegex = /\d/g;
let result = numString.match(numRegex).length; // Returns 3

22. Khớp tất cả không phải số

Bạn có muốn điều ngược lại và phù hợp với tất cả các số không phải là số không? Sử dụng\D

let numString = "Your sandwich will be $5.00";
// Match everything that is not a numberlet noNumRegex = /\D/g;
let result = numString.match(noNumRegex).length; // Returns 24

23. Hạn chế tên người dùng có thể

Càng xa càng tốt! Rất tốt cho việc làm cho nó đến nay. RegEx có thể phức tạp vì nó không phải là cách dễ đọc nhất để viết mã. Bây giờ chúng ta hãy xem xét một ví dụ rất thực tế và tạo một trình xác thực tên người dùng. Trong trường hợp này, bạn có 3 yêu cầu:

  • Nếu có số, chúng phải ở cuối.
  • Các chữ cái có thể là chữ thường và chữ hoa.
  • Dài ít nhất hai ký tự. Tên gồm hai chữ cái không được có số.

Hãy cố gắng giải quyết vấn đề này một mình và nếu bạn cảm thấy khó khăn hoặc chỉ muốn kiểm tra câu trả lời, hãy xem giải pháp của tôi.

24. Khớp khoảng trắng

Chúng ta có thể khớp tất cả các khoảng trắng không? Tất nhiên, chúng ta cũng có thể sử dụng cách viết tắt cho điều đó và nó\s

let sample = "Whitespace is important in separating words";
// Match all the whitespaceslet countWhiteSpace = /\s/g;
let result = sample.match(countWhiteSpace);
// Returns [" ", " ", " ", " ", " "]

25. Khớp các ký tự không có khoảng trắng

Bạn có thể đoán cách khớp tất cả các ký tự không có khoảng trắng không? Làm tốt lắm, nó \S!

let sample = "Whitespace is important in separating words";
// Match all non-whitespace characterslet countWhiteSpace = /\S/g;
let result = sample.match(countWhiteSpace);

26. Chỉ định số lượng khớp trên và dưới

Bạn có thể chỉ định số lượng mẫu phù hợp thấp hơn và trên với 'Chỉ định số lượng'. Chúng có thể được sử dụng với {}cú pháp, ví dụ {3,6}, đâu 3là giới hạn dưới và 6giới hạn trên được so khớp.

let ohStr = "Ohhh no";
// We want to match 'Oh's that have 3-6 'h' characters in it. let ohRegex = /Oh{3,6} no/;
let result = ohRegex.test(ohStr); // Returns true

27. Chỉ chỉ định số lượng phù hợp thấp hơn

Khi chúng ta chỉ muốn chỉ định giới hạn dưới, chúng ta có thể thực hiện bằng cách bỏ qua giới hạn trên, ví dụ để khớp với ít nhất ba ký tự mà chúng ta có thể viết {3,}. Lưu ý rằng chúng ta vẫn cần dấu phẩy, ngay cả khi chúng ta không chỉ định giới hạn trên.

let haStr = "Hazzzzah";
// Match a pattern that contains at least for 'z' characterslet haRegex = /z{4,}/;
let result = haRegex.test(haStr); // Returns true

28. Chỉ định Số lượng Kết hợp Chính xác

Trong phần trước, tôi đã đề cập rằng chúng ta cần dấu phẩy {3,}khi chúng ta chỉ xác định giới hạn dưới. Lý do là khi bạn viết {3}mà không có dấu phẩy, nghĩa là bạn đang muốn ghép chính xác 3 ký tự.

let timStr = "Timmmmber";
// let timRegex = /Tim{4}ber/;
let result = timRegex.test(timStr); // Returns true

29. Kiểm tra tất cả hoặc không

Đôi khi bạn có thể muốn chỉ định sự tồn tại có thể có của một ký tự trong mẫu của mình. Khi một chữ cái hoặc một số là tùy chọn và chúng tôi sẽ sử dụng ?cho điều đó.

// We want to match both British and American English spellings // of the word 'favourite'
let favWord_US = "favorite";let favWord_GB = "favourite";
// We match both 'favorite' and 'favourite' // by specifying that 'u' character is optionallet favRegex = /favou?rite/; // Change this line
let result1 = favRegex.test(favWord_US); // Returns truelet result2 = favRegex.test(favWord_GB); // Returns true

30. Cái nhìn tích cực và tiêu cực

' Lookahead ' là các mẫu yêu cầu JS của bạn nhìn trước để kiểm tra các mẫu xa hơn. Chúng hữu ích khi bạn đang cố gắng tìm kiếm nhiều mẫu trong cùng một chuỗi. Có 2 kiểu nhìn - tích cực và tiêu cực.

Tiêu đề tích cực sử dụng ?=cú pháp

let quit = "qu";
// We match 'q' only if it has 'u' after it. let quRegex= /q(?=u)/;
quit.match(quRegex); // Returns ["q"]

Tiêu đề phủ định sử dụng ?!cú pháp

let noquit = "qt";
// We match 'q' only if there is no 'u' after it. let qRegex = /q(?!u)/;
noquit.match(qRegex); // Returns ["q"]

31. Sử dụng lại các mẫu bằng cách sử dụng nhóm chụp

Hãy tưởng tượng chúng ta cần chụp một mẫu lặp lại.

let repeatStr = "regex regex";
// We want to match letters followed by space and then letterslet repeatRegex = /(\w+)\s(\w+)/;
repeatRegex.test(repeatStr); // Returns true

Thay vì lặp lại (\w+)ở cuối, chúng ta có thể yêu cầu RegEx lặp lại mẫu bằng cách sử dụng \1. Vì vậy, tương tự như trên có thể được viết lại thành:

let repeatStr = "regex regex";
let repeatRegex = /(\w+)\s\1)/;
repeatRegex.test(repeatStr); // Returns true

32. Sử dụng Capture Groups để tìm kiếm và thay thế

Khi chúng tôi tìm thấy một kết quả phù hợp, đôi khi rất tiện lợi để thay thế nó bằng một thứ khác. Chúng tôi có thể sử dụng replace()phương pháp cho điều đó.

let wrongText = "The sky is silver.";
let silverRegex = /silver/;
wrongText.replace(silverRegex, "blue");
// Returns "The sky is blue."

33. Xóa khoảng trắng khỏi Bắt đầu và Kết thúc

Đây là một thử thách nhỏ dành cho bạn. Viết một RegEx sẽ loại bỏ bất kỳ khoảng trắng nào xung quanh chuỗi.

let hello = " Hello, World! ";
let wsRegex = /change/; // Change this line
let result = hello; // Change this line

Nếu bạn gặp khó khăn hoặc chỉ muốn kiểm tra giải pháp của tôi, vui lòng xem diễn viên Scrimba nơi tôi giải quyết thử thách này.

34. Kết luận

Xin chúc mừng! Bạn đã hoàn thành khóa học này! Nếu bạn muốn tiếp tục tìm hiểu thêm, vui lòng xem danh sách phát YouTube này, danh sách này có rất nhiều dự án JavaScript mà bạn có thể tạo.

Hãy tiếp tục học hỏi và cảm ơn vì đã đọc!

Bây giờ bạn đã sẵn sàng để chơi gôn regex. ?