01/10/2018, 11:47

Xin ý kiến góp ý cho đoạn Code về sử dụng Regex trong Python

Em học đến phần Regex trong Python, em có làm 1 ví dụ với yêu cầu thế này:

Viết một chương trình Python để kiểm tra xem một chuỗi chỉ chứa
một tập ký tự nhất định (a-z, A-Z và 0-9) hay không .

Đoạn Code của e thế này:

import re
def is_check(string):
    charRe = re.compile(r'[a-zA-Z0-9]')
    string = charRe.search(string)
    return bool(string)

print(is_check("ABCDEFabcdef123450")) 
print(is_check("*&%@#!}{"))

Kết quả thu được:

True                                                                                                          
False 

Nhờ các anh/chị góp ý thêm cho em để Code hoàn thiện hơn ạ.

Dark.Hades viết 14:00 ngày 01/10/2018

Điều kiện bi thiếu

print(is_check("A{`*}*}*}"))
=> True

charRe = re.compile(r’[a-zA-Z0-9]’)

=>

charRe = re.compile(r'[a-zA-Z0-9]+$')
giang viết 14:00 ngày 01/10/2018

=>

charRe = re.compile(r’[a-zA-Z0-9]+$’)

Anh có thể giải thích giúp e vì sao lại phải thêm +$ được không ạ. Em cám ơn anh

giang viết 14:01 ngày 01/10/2018

mà anh ơi biểu thức Regex của anh đưa ra charRe = re.compile(r'[a-zA-Z0-9]+$')cũng chưa cho kq đúng trong trường hợp này :

print(is_check("***T"))
–>
KQ:True

Dark.Hades viết 13:47 ngày 01/10/2018

À mình quên

charRe = re.compile(r'^[a-zA-Z0-9]+$')

Nó là kiểm tra từ kí tự đầu tiên đến ký tự cuối cùng của 1 string

giang viết 13:47 ngày 01/10/2018

charRe = re.compile(r’^[a-zA-Z0-9]+$’)

Thế tại sao sau ký tự ^ không có dấu + mà trước ký tự $ lại phải có dấu + ạ ?

Dark.Hades viết 13:49 ngày 01/10/2018

Cặp dấu [] tức là kiểm tra 1 ký tự duy nhất, vậy nên phải thêm + để biểu thị kiếm tra nhiều hơn 1 ký tự nằm trong [], và $ tức là string đó phải kết thúc bằng ký tự phía trước nó.
Ký tự ^ biểu thị string phải bắt đầu bằng ký tự nằm sau nó

giang viết 13:50 ngày 01/10/2018

Cặp dấu [] tức là kiểm tra 1 ký tự duy nhất, vậy nên phải thêm + để biểu thị kiếm tra nhiều hơn 1 ký tự nằm trong [], và $ tức là string đó phải kết thúc bằng ký tự phía trước nó.
Ký tự ^ biểu thị string phải bắt đầu bằng ký tự nằm sau nó

Cảm ơn anh nhiều ạ. Em cũng hiểu sơ sơ rồi, bình thường nếu không bỏ ^$ vào thì nó sẽ khớp tại vị trí bất bỳ tức là nếu string có chứa ít nhất 1 ký tự thỏa mãn là nó đã trả về giá trị True rồi.

Em có tham khảo thêm đáp án thì thấy cách giải họ viết thế này:

import re
def is_check(string):
    charRe = re.compile(r'[^a-zA-Z0-9.]')
    string = charRe.search(string)
    return not bool(string)

print(is_check("ABCDEFabcdef123450")) 
print(is_check("*&%@#!}{"))

Trong Code có 1 số chỗ e chưa hiểu lắm.

  • ^ của họ lại đặt trong cặp[] chứ không ở bên ngoài giống cách của anh. Vậy đặt bê trong như vậy có nghĩa là thế nào ạ ?
  • Sao ở sau số 9 họ viết thêm dấu chấm . , em ko biết tác dụng của nó để làm gì, vì e bỏ đi thì thấy kq không thay đổi.
  • return not bool(string) và dòng lệnh này tại sao phải bỏ not vào đây ạ.

Anh có thể giải thích giúp e vs được không, e cảm ơn anh nhiều ạ

Dark.Hades viết 14:03 ngày 01/10/2018

Bạn đang dùng hàm search, hàm để regex đúng phải là match
Nội dung của 2 hàm này bạn search trực tiếp trên tàu liệu nhé

Dấu . thêm vào tức là thực hiện tìm cả dấu chấm đó, tất cả các ký tự nằm trong [] đều được tính là 1 char (ngoại trừ thằng range) và sẽ được nhét vào trong quy tắc hết. Bài của bạn thì phải bỏ đi vì đề không cho phép dấu chấm.
not ở đây là phủ định lại true, giả sử bạn search ra true thì nó sẽ trả về false

giang viết 13:54 ngày 01/10/2018

Hình như anh chưa giải thích cho e chổ này ạ.

^ của họ lại đặt trong cặp[] chứ không ở bên ngoài giống cách của anh. Vậy đặt bê trong như vậy có nghĩa là thế nào ạ ?

Còn not --> nó mang ý phủ định thì e biết rồi, vấn đề là em không hiểu tại sao phải thêm not vào đằng trước đó anh.

Dark.Hades viết 14:00 ngày 01/10/2018

Nội dung của 2 hàm này bạn search trực tiếp trên tàu liệu nhé

https://docs.python.org/2.0/lib/matching-searching.html

Viết code ra cho dễ hiểu:

wandbox.org

[Wandbox]三へ( へ՞ਊ ՞)へ ハッハッ

import re def is_search(string): charRe = re.compile(r'[^a-zA-Z0-9.]') string = charRe.search(string) return string def is_match(string): charRe = re.compile(r'^[a-zA-Z0-9.]+$')

giang viết 13:48 ngày 01/10/2018

re.compile(r'[^a-zA-Z0-9]')

Theo em hiểu thì dấu ^ đặt trước tập a-zA-Z0-9 và trong cặp []
mang ý nghĩa là phủ định : tức là nếu string chỉ cần chứa ít nhất 1 ký tự KHÔNG thuộc vào tập trên thì nó sẽ trả về True ngược lại nếu string KHÔNG chứa 1 ký tự nào KHÔNG thuộc vào tập trên thì sẽ trả về giá trị FALSE.
Không biết như vậy có đúng không. Mong anh cùng mọi người góp ý thêm ạ

Dark.Hades viết 13:59 ngày 01/10/2018

mang ý nghĩa là phủ định

Không phải nhé:

https://www.regular-expressions.info/anchors.html

giang viết 13:56 ngày 01/10/2018

Không phải nhé:

https://www.regular-expressions.info/anchors.html

Trong đó họ viết nó vẫn mang ý nghĩa là "khớp với vị trí trước ký tự đầu tiên trong chuỗi."
Nhưng mà sao với string này nó lại cho kq False hả anh.

import re

def is_allowed_specific_char(string):
    charRe = re.compile(r'[^a-zA-Z0-9]')
    string = charRe.search(string)
    return bool(string)
    
print(is_allowed_specific_char("ABCDEFabcdef123450")) ---> Flase
giang viết 13:59 ngày 01/10/2018

Không phải nhé:

https://www.regular-expressions.info/anchors.html

Em tìm được bài này:

Passionery

Regular Expression - Biểu thức chính quy là gì?

Regular expressions là một chuỗi ký tự đặc biệt được dùng làm mẫu (pattern) để phân tích sự trùng khớp của một tập hợp các chuỗi nào đó.


Người ta cũng nói như ý của em mà, hay là không biết Python có ngoại lệ không ?

giang viết 13:58 ngày 01/10/2018

anh ơi, Sao không thấy anh phản hồi lại ạ

Henry viết 13:47 ngày 01/10/2018

Hm…cứ print hết ra là hiểu vấn đề thôi. Mình sẽ đi từ trên xuống theo code bạn paste nhé
Giải sử ta có 3 tập hợp

  • Các chữ cái từ A -> Z
  • Các chữ cái từ a -> z
  • Các chữ số từ 0 -> 9
    Mình sẽ gọi cái tập hợp gồm 3 tập hợp này là domain nhé.
def is_check(string):
    charRe = re.compile(r'[a-zA-Z0-9]')
    string = charRe.search(string)
    return bool(string

Cái này dùng để kiếm trong chuỗi string của bạn có kí tự nào thuộc domain hay không. Nếu so với đề bài của bạn thì nó trật lất, vì chỉ cần có một kí tự thuộc domain thôi là coi như True. Đi ngược lại việc kiểm tra xem một chuỗi chỉ chứa
một tập ký tự nhất định (a-z, A-Z và 0-9) hay không

def is_check(string):
    charRe = re.compile(r'[^a-zA-Z0-9.]')
    string = charRe.search(string)
    return not bool(string)

Mình sẽ chia làm hai phần, phần đầu tiên

charRe = re.compile(r'[a-zA-Z0-9.]')
string = charRe.search(string)

Đoạn này khi search, nó sẽ tìm kiếm những kí tự thuộc domain và dấu '.'. Dấu chấm ở đây không phải kiểu dấu chấm đại diện cho bất kì kí tự nào đâu. Nó là dấu '.'
Và khi

charRe = re.compile(r'[^a-zA-Z0-9.]')

Có nghĩa là bạn đi phủ định lại cái đó bằng ‘^’. Còn nếu đặt ở ngoài là báo cho nó tìm ở đầu chuỗi
Tóm gọn lại nó sẽ tìm kiếm những kí tự KHÔNG thuộc domain và dấu '.'

return not bool(string)

Đoạn này thì dễ hiểu, nếu trên tìm được thì kết quả là False, tìm không được là True.
Cuối cùng thì cái đoạn code trên ấy, nó là một cách tuyệt vời để hoàn thành đề bài của bạn. Vì nó tìm phủ đinh nên sẽ tìm rộng hơn cái ban đầu của bạn

giang viết 13:58 ngày 01/10/2018

Em hiểu rồi. Cảm ơn anh nhiều ạ

giang viết 14:03 ngày 01/10/2018

Anh cho e hỏi thêm ý này nữa ạ.
Giữa 2 cách viết này có gì khác nhau ạ:

import re
tr = 'hello word'
kq = re.findall(r'h\w+',tr)
print kq

import re
tr = 'hello word'
kq = re.findall('h\w+',tr)
print kq

Khác nhau ở chỗ cách trên trong biểu thức chính quy có chữ r còn cách dưới thì không. Em ko biết chữ r đó có ý nghĩa gì ạ ?

HK boy viết 13:52 ngày 01/10/2018

r đó trước 1 string để biểu thị cho raw string.

Phải có r vì string thường sẽ không hiểu \ là kí tự \, còn raw_string thì có.

Bài liên quan
0