ដើម្បីអនុវត្តដំណើរការកន្សោមធម្មតានៅក្នុង Python យើងប្រើម៉ូឌុលឡើងវិញពីបណ្ណាល័យស្តង់ដារ។ វាអនុញ្ញាតឱ្យអ្នកស្រង់ ជំនួស និងបំបែកខ្សែអក្សរដោយប្រើលំនាំកន្សោមធម្មតា។
- re — Regular expression operations — Python 3.10.0 Documentation
- Regular Expression HOWTO — Python 3.10.0 Documentation
នៅក្នុងផ្នែកនេះ យើងនឹងពន្យល់ពីមុខងារ និងវិធីសាស្រ្តនៃ re module ជាដំបូង។
- ការចងក្រងគំរូកន្សោមធម្មតា៖
compile()
- វត្ថុដែលត្រូវគ្នា។
- ពិនិត្យមើលថាតើការចាប់ផ្តើមនៃខ្សែអក្សរត្រូវគ្នាឬអត់ ស្រង់ចេញ៖
match()
- ពិនិត្យមើលការប្រកួតមិនកំណត់ចំពោះការចាប់ផ្តើមទេ៖
search()
- ពិនិត្យមើលថាតើខ្សែអក្សរទាំងមូលត្រូវគ្នាដែរឬទេ៖
fullmatch()
- ទទួលបានបញ្ជីនៃផ្នែកដែលត្រូវគ្នាទាំងអស់៖
findall()
- ទទួលបានផ្នែកដែលត្រូវគ្នាទាំងអស់ជាអ្នកធ្វើឡើងវិញ៖
finditer()
- ជំនួសផ្នែកដែលត្រូវគ្នា៖
sub()
,subn()
- ការបំបែកខ្សែអក្សរជាមួយនឹងលំនាំកន្សោមធម្មតា៖
split()
បន្ទាប់ពីនោះ ខ្ញុំនឹងពន្យល់តួអក្សរមេតា (តួអក្សរពិសេស) និងលំដាប់ពិសេសនៃកន្សោមធម្មតាដែលអាចប្រើក្នុងម៉ូឌុលឡើងវិញ។ ជាទូទៅវាគឺជាវាក្យសម្ព័ន្ធកន្សោមធម្មតាស្តង់ដារ ប៉ុន្តែត្រូវប្រយ័ត្នចំពោះការកំណត់ទង់ (ជាពិសេស re.ASCII)។
- metacharacters កន្សោមធម្មតា លំដាប់ពិសេស និងការព្រមាននៅក្នុង Python
- ការកំណត់ទង់ជាតិ
- កំណត់ចំពោះតួអក្សរ ASCII៖
re.ASCII
- មិនប្រកាន់អក្សរតូចធំ៖
re.IGNORECASE
- ផ្គូផ្គងការចាប់ផ្តើម និងចុងបញ្ចប់នៃបន្ទាត់នីមួយៗ៖
re.MULTILINE
- បញ្ជាក់ទង់ជាច្រើន។
- កំណត់ចំពោះតួអក្សរ ASCII៖
- ការផ្គូផ្គងលោភលន់និងមិនលោភលន់
- ចងក្រងលំនាំកន្សោមធម្មតា៖ ចងក្រង()
- វត្ថុដែលត្រូវគ្នា។
- ពិនិត្យមើលថាតើការចាប់ផ្តើមនៃខ្សែអក្សរត្រូវគ្នាឬអត់ ស្រង់ចេញ៖ match()
- ពិនិត្យមើលការផ្គូផ្គងមិនកំណត់ចំពោះការចាប់ផ្តើមឡើយ ស្រង់ចេញ៖ search()
- ពិនិត្យមើលថាតើខ្សែអក្សរទាំងមូលត្រូវគ្នាដែរឬទេ៖ fullmatch()
- ទទួលបានបញ្ជីនៃផ្នែកដែលត្រូវគ្នាទាំងអស់៖ findall()
- ទទួលបានផ្នែកដែលត្រូវគ្នាទាំងអស់ជាអ្នកធ្វើឡើងវិញ៖ finditer()
- ជំនួសផ្នែកដែលត្រូវគ្នា៖ sub(), subn()
- ការបំបែកខ្សែអក្សរជាមួយនឹងលំនាំកន្សោមធម្មតា៖ split()
- metacharacters កន្សោមធម្មតា លំដាប់ពិសេស និងការព្រមាននៅក្នុង Python
- ការកំណត់ទង់ជាតិ
- ការផ្គូផ្គងលោភលន់និងមិនលោភលន់
ចងក្រងលំនាំកន្សោមធម្មតា៖ ចងក្រង()
មានវិធីពីរយ៉ាងដើម្បីដំណើរការកន្សោមធម្មតានៅក្នុងម៉ូឌុលឡើងវិញ។
ដំណើរការជាមួយមុខងារ
ទីមួយគឺជាមុខងារ។re.match()
,re.sub()
មុខងារដូចនេះគឺអាចប្រើបានដើម្បីអនុវត្តការស្រង់ចេញ ការជំនួស និងដំណើរការផ្សេងទៀតដោយប្រើលំនាំកន្សោមធម្មតា។
ព័ត៌មានលម្អិតនៃមុខងារនឹងត្រូវបានពិពណ៌នានៅពេលក្រោយ ប៉ុន្តែនៅក្នុងទាំងអស់នោះ អាគុយម៉ង់ទីមួយគឺខ្សែអក្សរនៃគំរូកន្សោមធម្មតា បន្ទាប់មកខ្សែអក្សរដែលត្រូវដំណើរការជាដើម។ ឧទាហរណ៍ នៅក្នុង re.sub() ដែលអនុវត្តការជំនួស អាគុយម៉ង់ទីពីរគឺជាខ្សែអក្សរជំនួស ហើយអាគុយម៉ង់ទីបីគឺជាខ្សែដែលត្រូវដំណើរការ។
import re
s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'
m = re.match(r'([a-z]+)@([a-z]+)\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
result = re.sub(r'([a-z]+)@([a-z]+)\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net
ចំណាំថា [a-z] នៅក្នុងលំនាំកន្សោមធម្មតាក្នុងឧទាហរណ៍នេះមានន័យថាតួអក្សរណាមួយពី a ដល់ z (ឧ. [a-z]+ ត្រូវនឹងខ្សែអក្សរណាដែលសរសេរអក្សរតូចមួយ ឬច្រើនឡើងវិញ។
. គឺជាតួអក្សរមេតា (តួអក្សរដែលមានអត្ថន័យពិសេស) ហើយត្រូវតែគេចចេញដោយប្រើសញ្ញាសម្គាល់ខាងក្រោយ។
ដោយសារខ្សែអក្សរលំនាំកន្សោមធម្មតាតែងតែប្រើ backslashes ច្រើន វាងាយស្រួលប្រើខ្សែអក្សរឆៅដូចក្នុងឧទាហរណ៍។
ដំណើរការក្នុងវិធីសាស្រ្តនៃវត្ថុលំនាំកន្សោមធម្មតា។
វិធីទីពីរដើម្បីដំណើរការកន្សោមធម្មតានៅក្នុងម៉ូឌុលឡើងវិញគឺជាវិធីសាស្ត្រវត្ថុគំរូកន្សោមធម្មតា។
ដោយប្រើ re.compile() អ្នកអាចចងក្រងខ្សែអក្សរលំនាំកន្សោមធម្មតា ដើម្បីបង្កើតវត្ថុគំរូកន្សោមធម្មតា។
p = re.compile(r'([a-z]+)@([a-z]+)\.com')
print(p)
# re.compile('([a-z]+)@([a-z]+)\\.com')
print(type(p))
# <class 're.Pattern'>
re.match()
,re.sub()
ឧទាហរណ៍ ដំណើរការដូចគ្នាទៅនឹងមុខងារទាំងនេះអាចត្រូវបានប្រតិបត្តិជាវិធីសាស្រ្ត match(),sub() នៃវត្ថុកន្សោមធម្មតា។
m = p.match(s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
result = p.sub('new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net
មុខងារ re.xxx() ទាំងអស់ដែលបានពិពណ៌នាខាងក្រោមក៏ត្រូវបានផ្តល់ជាវិធីសាស្រ្តនៃវត្ថុកន្សោមធម្មតា។
ប្រសិនបើអ្នកកំពុងដំណើរការឡើងវិញនូវដំណើរការដែលប្រើលំនាំដូចគ្នា វាកាន់តែមានប្រសិទ្ធភាពក្នុងការបង្កើតវត្ថុកន្សោមធម្មតាជាមួយ re.compile() ហើយប្រើវាជុំវិញ។
នៅក្នុងកូដគំរូខាងក្រោម អនុគមន៍ត្រូវបានប្រើដោយមិនចងក្រងដើម្បីភាពងាយស្រួល ប៉ុន្តែប្រសិនបើអ្នកចង់ប្រើលំនាំដដែលដដែលៗ វាត្រូវបានណែនាំឱ្យចងក្រងវាជាមុន ហើយប្រតិបត្តិវាជាវិធីសាស្ត្រនៃវត្ថុកន្សោមធម្មតា។
វត្ថុដែលត្រូវគ្នា។
match(), search() ។ល។ ត្រឡប់វត្ថុដែលត្រូវគ្នា។
s = 'aaa@xxx.com'
m = re.match(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
print(type(m))
# <class 're.Match'>
ខ្សែអក្សរ និងទីតាំងដែលត្រូវគ្នាត្រូវបានទទួលដោយប្រើវិធីសាស្ត្រខាងក្រោមនៃវត្ថុដែលត្រូវគ្នា។
- ទទួលបានទីតាំងនៃការប្រកួត៖
start()
,end()
,span()
- ទទួលបានខ្សែដែលត្រូវគ្នា៖
group()
- ទទួលបានខ្សែអក្សរសម្រាប់ក្រុមនីមួយៗ៖
groups()
print(m.start())
# 0
print(m.end())
# 11
print(m.span())
# (0, 11)
print(m.group())
# aaa@xxx.com
ប្រសិនបើអ្នកភ្ជាប់ផ្នែកមួយនៃគំរូកន្សោមធម្មតានៅក្នុងខ្សែអក្សរដែលមានវង់ក្រចក() ផ្នែកនឹងត្រូវបានដំណើរការជាក្រុម។ ក្នុងករណីនេះ ខ្សែនៃផ្នែកដែលត្រូវគ្នានឹងក្រុមនីមួយៗក្នុងក្រុម() អាចទទួលបានជា tuple ។
m = re.match(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
print(m.groups())
# ('aaa', 'xxx', 'com')
ពិនិត្យមើលថាតើការចាប់ផ្តើមនៃខ្សែអក្សរត្រូវគ្នាឬអត់ ស្រង់ចេញ៖ match()
match() ត្រឡប់វត្ថុដែលត្រូវគ្នា ប្រសិនបើការចាប់ផ្តើមនៃខ្សែអក្សរត្រូវគ្នានឹងលំនាំ។
ដូចដែលបានរៀបរាប់ខាងលើ វត្ថុផ្គូផ្គងអាចត្រូវបានប្រើដើម្បីស្រង់ខ្សែអក្សររងដែលត្រូវគ្នា ឬគ្រាន់តែពិនិត្យមើលថាតើការផ្គូផ្គងមួយត្រូវបានធ្វើឡើងឬអត់។
match() នឹងពិនិត្យតែការចាប់ផ្តើមប៉ុណ្ណោះ។ ប្រសិនបើមិនមានខ្សែអក្សរដែលត្រូវគ្នានៅដើមទេ វាត្រឡប់គ្មាន។
s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'
m = re.match(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
m = re.match(r'[a-z]+@[a-z]+\.net', s)
print(m)
# None
ពិនិត្យមើលការផ្គូផ្គងមិនកំណត់ចំពោះការចាប់ផ្តើមឡើយ ស្រង់ចេញ៖ search()
ដូចជា match() វាត្រឡប់វត្ថុដែលត្រូវគ្នាប្រសិនបើវាត្រូវគ្នា។
ប្រសិនបើមានផ្នែកផ្គូផ្គងច្រើន មានតែផ្នែកដែលត្រូវគ្នាដំបូងប៉ុណ្ណោះដែលនឹងត្រូវប្រគល់មកវិញ។
s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'
m = re.search(r'[a-z]+@[a-z]+\.net', s)
print(m)
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>
m = re.search(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
ប្រសិនបើអ្នកចង់ទទួលបានផ្នែកដែលត្រូវគ្នាទាំងអស់ សូមប្រើ findall() ឬ finditer() ដូចដែលបានពិពណ៌នាខាងក្រោម។
ពិនិត្យមើលថាតើខ្សែអក្សរទាំងមូលត្រូវគ្នាដែរឬទេ៖ fullmatch()
ដើម្បីពិនិត្យមើលថាតើខ្សែអក្សរទាំងមូលត្រូវគ្នានឹងលំនាំកន្សោមធម្មតា សូមប្រើ fullmatch()។ នេះមានប្រយោជន៍ ជាឧទាហរណ៍ ដើម្បីពិនិត្យមើលថាតើខ្សែអក្សរមួយមានសុពលភាពជាអាសយដ្ឋានអ៊ីមែលឬអត់។
ប្រសិនបើខ្សែអក្សរទាំងមូលត្រូវគ្នា វត្ថុដែលត្រូវគ្នានឹងត្រលប់មកវិញ។
s = 'aaa@xxx.com'
m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
ប្រសិនបើមានផ្នែកដែលមិនផ្គូផ្គង (គ្រាន់តែផ្គូផ្គងផ្នែកខ្លះ ឬគ្មានការផ្គូផ្គងទាំងអស់) គ្មានផ្នែកណាមួយត្រូវបានត្រឡប់មកវិញទេ។
s = '!!!aaa@xxx.com!!!'
m = re.fullmatch(r'[a-z]+@[a-z]+\.com', s)
print(m)
# None
fullmatch() ត្រូវបានបន្ថែមនៅក្នុង Python 3.4។ ប្រសិនបើអ្នកចង់ធ្វើដូចគ្នានៅក្នុងកំណែមុន សូមប្រើ match() និងតួអក្សរមេតាដែលត្រូវគ្នា $ នៅចុងបញ្ចប់។ ប្រសិនបើខ្សែអក្សរទាំងមូលពីដើមដល់ចប់មិនត្រូវគ្នា វាត្រឡប់គ្មាន។
s = '!!!aaa@xxx.com!!!'
m = re.match(r'[a-z]+@[a-z]+\.com$', s)
print(m)
# None
ទទួលបានបញ្ជីនៃផ្នែកដែលត្រូវគ្នាទាំងអស់៖ findall()
findall() ត្រឡប់បញ្ជីនៃខ្សែរងដែលត្រូវគ្នាទាំងអស់។ ចំណាំថាធាតុនៃបញ្ជីមិនមែនជាវត្ថុដែលត្រូវគ្នាទេ ប៉ុន្តែជាខ្សែអក្សរ។
s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'
result = re.findall(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# ['aaa@xxx.com', 'bbb@yyy.com', 'ccc@zzz.net']
ចំនួននៃផ្នែកដែលត្រូវគ្នាអាចត្រូវបានពិនិត្យដោយប្រើមុខងារដែលភ្ជាប់មកជាមួយ len() ដែលត្រឡប់ចំនួនធាតុនៅក្នុងបញ្ជី។
print(len(result))
# 3
ការដាក់ជាក្រុមជាមួយនឹងវង់ក្រចក() នៅក្នុងលំនាំកន្សោមធម្មតា ត្រឡប់បញ្ជីនៃ tuples ដែលធាតុទាំងនោះជាខ្សែនៃក្រុមនីមួយៗ។ នេះគឺស្មើនឹងក្រុម() នៅក្នុងវត្ថុដែលត្រូវគ្នា។
result = re.findall(r'([a-z]+)@([a-z]+)\.([a-z]+)', s)
print(result)
# [('aaa', 'xxx', 'com'), ('bbb', 'yyy', 'com'), ('ccc', 'zzz', 'net')]
វង់ក្រចកក្រុម () អាចដាក់ក្នុងវង់ក្រចក ដូច្នេះប្រសិនបើអ្នកចង់ទទួលបានការប្រកួតទាំងមូលផងដែរ គ្រាន់តែភ្ជាប់ការប្រកួតទាំងមូលនៅក្នុងវង់ក្រចក ()។
result = re.findall(r'(([a-z]+)@([a-z]+)\.([a-z]+))', s)
print(result)
# [('aaa@xxx.com', 'aaa', 'xxx', 'com'), ('bbb@yyy.com', 'bbb', 'yyy', 'com'), ('ccc@zzz.net', 'ccc', 'zzz', 'net')]
ប្រសិនបើរកមិនឃើញការផ្គូផ្គងទេ នោះ tuple ទទេនឹងត្រលប់មកវិញ។
result = re.findall('[0-9]+', s)
print(result)
# []
ទទួលបានផ្នែកដែលត្រូវគ្នាទាំងអស់ជាអ្នកធ្វើឡើងវិញ៖ finditer()
finditer() ត្រឡប់ផ្នែកដែលត្រូវគ្នាទាំងអស់ជាអ្នកធ្វើឡើងវិញ។ ធាតុមិនមែនជាខ្សែអក្សរដូចជា findall() ប៉ុន្តែត្រូវគ្នានឹងវត្ថុ ដូច្នេះអ្នកអាចទទួលបានទីតាំង (សន្ទស្សន៍) នៃផ្នែកដែលត្រូវគ្នា។
អក្សរកាត់ខ្លួនវាមិនអាចត្រូវបានបោះពុម្ពចេញដោយ print() ដើម្បីទទួលបានមាតិការបស់វា។ ប្រសិនបើអ្នកប្រើមុខងារដែលភ្ជាប់មកជាមួយ next() ឬសម្រាប់សេចក្តីថ្លែងការណ៍ អ្នកអាចទទួលបានមាតិកាម្តងមួយៗ។
s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'
result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)
print(result)
# <callable_iterator object at 0x10b0efa90>
print(type(result))
# <class 'callable_iterator'>
for m in result:
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>
វាក៏អាចបំប្លែងទៅជាបញ្ជីដែលមាន list() ផងដែរ។
l = list(re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s))
print(l)
# [<re.Match object; span=(0, 11), match='aaa@xxx.com'>, <re.Match object; span=(13, 24), match='bbb@yyy.com'>, <re.Match object; span=(26, 37), match='ccc@zzz.net'>]
print(l[0])
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
print(type(l[0]))
# <class 're.Match'>
print(l[0].span())
# (0, 11)
ប្រសិនបើអ្នកចង់ទទួលបានទីតាំងនៃផ្នែកដែលត្រូវគ្នាទាំងអស់នោះ ការកំណត់ការយល់ក្នុងបញ្ជីគឺងាយស្រួលជាង list()។
print([m.span() for m in re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)])
# [(0, 11), (13, 24), (26, 37)]
អ្នកបង្វែរធាតុតាមលំដាប់លំដោយ។ ចំណាំថាប្រសិនបើអ្នកព្យាយាមទាញយកធាតុបន្ថែមទៀតបន្ទាប់ពីឈានដល់ទីបញ្ចប់ អ្នកនឹងលែងមានអ្វីទាំងអស់។
result = re.finditer(r'[a-z]+@[a-z]+\.[a-z]+', s)
for m in result:
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
# <re.Match object; span=(13, 24), match='bbb@yyy.com'>
# <re.Match object; span=(26, 37), match='ccc@zzz.net'>
print(list(result))
# []
ជំនួសផ្នែកដែលត្រូវគ្នា៖ sub(), subn()
ដោយប្រើ sub() អ្នកអាចជំនួសផ្នែកដែលត្រូវគ្នាជាមួយនឹងខ្សែអក្សរផ្សេងទៀត។ ខ្សែអក្សរដែលបានជំនួសនឹងត្រូវបានត្រឡប់មកវិញ។
s = 'aaa@xxx.com, bbb@yyy.com, ccc@zzz.net'
result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# new-address, new-address, ccc@zzz.net
print(type(result))
# <class 'str'>
នៅពេលដាក់ជាក្រុមជាមួយវង់ក្រចក() ខ្សែអក្សរដែលត្រូវគ្នាអាចត្រូវបានប្រើនៅក្នុងខ្សែអក្សរដែលបានជំនួស។
តាមលំនាំដើម ចំណុចខាងក្រោមត្រូវបានគាំទ្រ៖ ចំណាំថាសម្រាប់ខ្សែធម្មតាដែលមិនមែនជាខ្សែអក្សរដើម សញ្ញាថយក្រោយត្រូវតែត្រូវបានរាយបញ្ជីនៅពីមុខ backslash ដើម្បីគេចពី backslash ។
\1 | វង់ក្រចកទីមួយ |
\2 | វង់ក្រចកទីពីរ |
\3 | វង់ក្រចកទីបី |
result = re.sub(r'([a-z]+)@([a-z]+)\.com', r'\1@\2.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net
?P<xxx>
ប្រសិនបើអ្នកដាក់ឈ្មោះក្រុមដោយសរសេរវានៅដើមវង់ក្រចកនៃគំរូកន្សោមធម្មតា អ្នកអាចបញ្ជាក់វាដោយប្រើឈ្មោះជំនួសឱ្យលេខដូចបានបង្ហាញខាងក្រោម។\g<xxx>
result = re.sub(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# aaa@xxx.net, bbb@yyy.net, ccc@zzz.net
ចំនួនអាគុយម៉ង់បញ្ជាក់ចំនួនអតិបរមានៃការជំនួស។ មានតែការរាប់ពីផ្នែកខាងឆ្វេងប៉ុណ្ណោះនឹងត្រូវបានជំនួស។
result = re.sub(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# new-address, bbb@yyy.com, ccc@zzz.net
subn() ត្រឡប់ tuple នៃខ្សែអក្សរដែលបានជំនួស (ដូចគ្នានឹងតម្លៃត្រឡប់នៃ sub()) និងចំនួននៃផ្នែកជំនួស (ចំនួនដែលត្រូវនឹងលំនាំ)។
result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s)
print(result)
# ('new-address, new-address, ccc@zzz.net', 2)
វិធីសាស្រ្តនៃការបញ្ជាក់អាគុយម៉ង់គឺដូចគ្នានឹង sub() ។ អ្នកអាចប្រើផ្នែកដែលដាក់ជាក្រុមដោយវង់ក្រចក ឬបញ្ជាក់ចំនួនអាគុយម៉ង់។
result = re.subn(r'(?P<local>[a-z]+)@(?P<SLD>[a-z]+)\.com', r'\g<local>@\g<SLD>.net', s)
print(result)
# ('aaa@xxx.net, bbb@yyy.net, ccc@zzz.net', 2)
result = re.subn(r'[a-z]+@[a-z]+\.com', 'new-address', s, count=1)
print(result)
# ('new-address, bbb@yyy.com, ccc@zzz.net', 1)
ការបំបែកខ្សែអក្សរជាមួយនឹងលំនាំកន្សោមធម្មតា៖ split()
split() បំបែកខ្សែអក្សរនៅផ្នែកដែលត្រូវនឹងលំនាំ ហើយត្រឡប់វាជាបញ្ជី។
ចំណាំថាការផ្គូផ្គងដំបូង និងចុងក្រោយនឹងមានខ្សែទទេនៅដើម និងចុងបញ្ចប់នៃបញ្ជីលទ្ធផល។
s = '111aaa222bbb333'
result = re.split('[a-z]+', s)
print(result)
# ['111', '222', '333']
result = re.split('[0-9]+', s)
print(result)
# ['', 'aaa', 'bbb', '']
អាគុយម៉ង់ maxsplit បញ្ជាក់ចំនួនអតិបរមានៃការបំបែក (បំណែក) ។ មានតែការរាប់ពីផ្នែកខាងឆ្វេងប៉ុណ្ណោះដែលនឹងត្រូវបំបែក។
result = re.split('[a-z]+', s, 1)
print(result)
# ['111', '222bbb333']
metacharacters កន្សោមធម្មតា លំដាប់ពិសេស និងការព្រមាននៅក្នុង Python
តួអក្សរមេតាកន្សោមធម្មតាចម្បង (តួអក្សរពិសេស) និងលំដាប់ពិសេសដែលអាចប្រើក្នុងម៉ូឌុល Python 3 re មានដូចខាងក្រោម
តួអក្សរមេតា | មាតិកា |
---|---|
. | តួអក្សរតែមួយក្រៅពីបន្ទាត់ថ្មី (រួមទាំងបន្ទាត់ថ្មីដែលមានទង់ DOTALL) |
^ | ការចាប់ផ្តើមនៃខ្សែអក្សរ (ក៏ត្រូវគ្នានឹងការចាប់ផ្តើមនៃបន្ទាត់នីមួយៗដែលមានទង់ MULTILINE) |
$ | ចុងបញ្ចប់នៃខ្សែអក្សរ (ក៏ត្រូវគ្នានឹងចុងបញ្ចប់នៃបន្ទាត់នីមួយៗដែលមានទង់ MULTILINE) |
* | ធ្វើលំនាំមុនម្តងទៀតច្រើនជាង 0 ដង |
+ | ធ្វើលំនាំមុនម្តងទៀតយ៉ាងហោចណាស់ម្តង។ |
? | ធ្វើម្តងទៀតនូវលំនាំមុន 0 ឬ 1 ដង |
{m} | ធ្វើម្តងទៀតនូវលំនាំមុន m ដង |
{m, n} | លំនាំចុងក្រោយ។m ~n ធ្វើម្តងទៀត |
[] | សំណុំនៃតួអក្សរ[] ផ្គូផ្គងតួអក្សរណាមួយក្នុងចំណោមតួអក្សរទាំងនេះ |
| | ឬA|B ផ្គូផ្គងលំនាំ A ឬ B |
លំដាប់ពិសេស | មាតិកា |
---|---|
\d | លេខទសភាគយូនីកូដ (កំណត់ត្រឹមលេខ ASCII ដោយទង់ ASCII) |
\D | \d មានន័យផ្ទុយពីនេះ។ |
\s | តួអក្សរដកឃ្លាយូនីកូដ (កំណត់ចំពោះតួអក្សរដកឃ្លា ASCII ដោយទង់ ASCII) |
\S | \s មានន័យផ្ទុយពីនេះ។ |
\w | អក្សរយូនីកូដ និងសញ្ញាគូសក្រោម (កំណត់ចំពោះតួអក្សរលេខ ASCII និងសញ្ញាគូសក្រោមដោយទង់ ASCII) |
\W | \w មានន័យផ្ទុយពីនេះ។ |
មិនមែនពួកគេទាំងអស់ត្រូវបានរាយក្នុងតារាងនេះទេ។ សូមមើលឯកសារផ្លូវការសម្រាប់បញ្ជីពេញលេញ។
សូមចំណាំផងដែរថា អត្ថន័យខ្លះមានភាពខុសគ្នានៅក្នុង Python 2 ។
ការកំណត់ទង់ជាតិ
ដូចដែលបានបង្ហាញក្នុងតារាងខាងលើ តួអក្សរមេតាមួយចំនួន និងលំដាប់ពិសេសផ្លាស់ប្តូររបៀបរបស់វាអាស្រ័យលើទង់។
មានតែទង់ជាតិសំខាន់ៗប៉ុណ្ណោះដែលត្រូវបានគ្របដណ្តប់នៅទីនេះ។ សូមមើលឯកសារផ្លូវការសម្រាប់នៅសល់។
កំណត់ចំពោះតួអក្សរ ASCII៖ re.ASCII
\w
វាក៏នឹងត្រូវគ្នានឹងអក្សរខនជីទ្វេបៃ អក្សរលេខជាដើមតាមលំនាំដើមសម្រាប់ខ្សែអក្សរ Python 3។ វាមិនស្មើនឹងពាក្យខាងក្រោមទេ ព្រោះវាមិនមែនជាកន្សោមធម្មតាស្តង់ដារ។[a-zA-Z0-9_]
m = re.match(r'\w+', '漢字ABC123')
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>
m = re.match('[a-zA-Z0-9_]+', '漢字ABC123')
print(m)
# None
ប្រសិនបើអ្នកបញ្ជាក់ re.ASCII សម្រាប់ទង់អាគុយម៉ង់នៅក្នុងមុខងារនីមួយៗ ឬបន្ថែមទង់ក្នុងជួរខាងក្រោមទៅដើមនៃខ្សែអក្សរលំនាំកន្សោមធម្មតា វានឹងផ្គូផ្គងតែតួអក្សរ ASCII ប៉ុណ្ណោះ (វានឹងមិនត្រូវគ្នានឹងទ្វេបៃជាភាសាជប៉ុន អក្សរក្រមលេខ ។ល។ .)(?a)
ក្នុងករណីនេះ ពីរខាងក្រោមគឺសមមូល។\w
#ERROR![a-zA-Z0-9_]
m = re.match(r'\w+', '漢字ABC123', flags=re.ASCII)
print(m)
# None
m = re.match(r'(?a)\w+', '漢字ABC123')
print(m)
# None
ដូចគ្នានេះដែរអនុវត្តនៅពេលចងក្រងជាមួយ re.compile() ។ ប្រើទង់អាគុយម៉ង់ ឬទង់ក្នុងជួរ។
p = re.compile(r'\w+', flags=re.ASCII)
print(p)
# re.compile('\\w+', re.ASCII)
print(p.match('漢字ABC123'))
# None
p = re.compile(r'(?a)\w+')
print(p)
# re.compile('(?a)\\w+', re.ASCII)
print(p.match('漢字ABC123'))
# None
ASCII ក៏មានផងដែរជាទម្រង់ខ្លី។ A. អ្នកអាចប្រើទាំង។
print(re.ASCII is re.A)
# True
\W ដែលផ្ទុយពី \W ក៏ត្រូវបានប៉ះពាល់ផងដែរដោយ re.ASCII និងទង់ក្នុងជួរ។
m = re.match(r'\W+', '漢字ABC123')
print(m)
# None
m = re.match(r'\W+', '漢字ABC123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 11), match='漢字ABC123'>
ដូចនឹង \w ពីរខាងក្រោមត្រូវគ្នាទាំងតួអក្សរមួយបៃ និងពីរបៃតាមលំនាំដើម ប៉ុន្តែត្រូវបានកំណត់ចំពោះតួអក្សរតែមួយបៃ ប្រសិនបើ re.ASCII ឬទង់ក្នុងជួរត្រូវបានបញ្ជាក់។
- ផ្គូផ្គងលេខ
\d
- ផ្គូផ្គងចន្លោះទទេ
\s
- ផ្គូផ្គងមិនមែនលេខ
\D
- ផ្គូផ្គងគ្មានចន្លោះ។
\S
m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>
m = re.match(r'\d+', '123')
print(m)
# <re.Match object; span=(0, 3), match='123'>
m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# <re.Match object; span=(0, 3), match='123'>
m = re.match(r'\d+', '123', flags=re.ASCII)
print(m)
# None
m = re.match(r'\s+', ' ') # full-width space
print(m)
# <re.Match object; span=(0, 1), match='\u3000'>
m = re.match(r'\s+', ' ', flags=re.ASCII)
print(m)
# None
មិនប្រកាន់អក្សរតូចធំ៖re.IGNORECASE
តាមលំនាំដើម វាជាអក្សរតូចធំ។ ដើម្បីផ្គូផ្គងទាំងពីរ អ្នកត្រូវបញ្ចូលទាំងអក្សរធំ និងអក្សរតូចនៅក្នុងលំនាំ។
re.IGNORECASE
ប្រសិនបើវាត្រូវបានបញ្ជាក់ វានឹងផ្គូផ្គងករណីដែលមិនប្រកាន់អក្សរតូចធំ។ ស្មើនឹងទង់ i នៅក្នុងកន្សោមធម្មតាស្តង់ដារ។
m = re.match('[a-zA-Z]+', 'abcABC')
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>
m = re.match('[a-z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>
m = re.match('[A-Z]+', 'abcABC', flags=re.IGNORECASE)
print(m)
# <re.Match object; span=(0, 6), match='abcABC'>
អ្នកអាចប្រើតិចជាង ឬស្មើ។
- ទង់ជាតិក្នុងជួរ
(?i)
- អក្សរកាត់
re.I
ផ្គូផ្គងការចាប់ផ្តើម និងចុងបញ្ចប់នៃបន្ទាត់នីមួយៗ៖re.MULTILINE
^
តួអក្សរមេតានៅក្នុងកន្សោមធម្មតានេះត្រូវគ្នានឹងការចាប់ផ្តើមនៃខ្សែអក្សរ។
តាមលំនាំដើម មានតែការចាប់ផ្តើមនៃខ្សែអក្សរទាំងមូលប៉ុណ្ណោះដែលត្រូវបានផ្គូផ្គង ប៉ុន្តែខាងក្រោមនេះនឹងផ្គូផ្គងការចាប់ផ្តើមនៃបន្ទាត់នីមួយៗផងដែរ។ ស្មើនឹងទង់ m ក្នុងកន្សោមធម្មតាស្តង់ដារ។re.MULTILINE
s = '''aaa-xxx
bbb-yyy
ccc-zzz'''
print(s)
# aaa-xxx
# bbb-yyy
# ccc-zzz
result = re.findall('[a-z]+', s)
print(result)
# ['aaa', 'xxx', 'bbb', 'yyy', 'ccc', 'zzz']
result = re.findall('^[a-z]+', s)
print(result)
# ['aaa']
result = re.findall('^[a-z]+', s, flags=re.MULTILINE)
print(result)
# ['aaa', 'bbb', 'ccc']
$
ផ្គូផ្គងចុងបញ្ចប់នៃខ្សែអក្សរ។ តាមលំនាំដើម មានតែចុងបញ្ចប់នៃខ្សែអក្សរទាំងមូលប៉ុណ្ណោះដែលត្រូវបានផ្គូផ្គង។re.MULTILINE
ប្រសិនបើអ្នកបញ្ជាក់ចំណុចនេះ វាក៏នឹងផ្គូផ្គងចុងបញ្ចប់នៃបន្ទាត់នីមួយៗផងដែរ។
result = re.findall('[a-z]+$', s)
print(result)
# ['zzz']
result = re.findall('[a-z]+$', s, flags=re.MULTILINE)
print(result)
# ['xxx', 'yyy', 'zzz']
អ្នកអាចប្រើតិចជាង ឬស្មើ។
- ទង់ជាតិក្នុងជួរ
(?m)
- អក្សរកាត់
re.M
បញ្ជាក់ទង់ជាច្រើន។
|
ប្រសិនបើអ្នកចង់បើកទង់ច្រើនក្នុងពេលតែមួយ សូមប្រើវា។ ក្នុងករណីទង់ក្នុងជួរ តួអក្សរនីមួយៗត្រូវតែតាមដោយអក្សរដូចបង្ហាញខាងក្រោម។(?am)
s = '''aaa-xxx
漢漢漢-字字字
bbb-zzz'''
print(s)
# aaa-xxx
# 漢漢漢-字字字
# bbb-zzz
result = re.findall(r'^\w+', s, flags=re.M)
print(result)
# ['aaa', '漢漢漢', 'bbb']
result = re.findall(r'^\w+', s, flags=re.M | re.A)
print(result)
# ['aaa', 'bbb']
result = re.findall(r'(?am)^\w+', s)
print(result)
# ['aaa', 'bbb']
ការផ្គូផ្គងលោភលន់និងមិនលោភលន់
នេះគឺជាបញ្ហាទូទៅជាមួយនឹងកន្សោមធម្មតា មិនមែនគ្រាន់តែជាបញ្ហាជាមួយ Python នោះទេ ប៉ុន្តែខ្ញុំនឹងសរសេរអំពីវាព្រោះវាមានទំនោរធ្វើឱ្យខ្ញុំមានបញ្ហា។
តាមលំនាំដើម ខាងក្រោមនេះគឺជាការផ្គូផ្គងលោភលន់ ដែលផ្គូផ្គងខ្សែអក្សរដែលវែងបំផុតដែលអាចធ្វើទៅបាន។
*
+
?
s = 'aaa@xxx.com, bbb@yyy.com'
m = re.match(r'.+com', s)
print(m)
# <re.Match object; span=(0, 24), match='aaa@xxx.com, bbb@yyy.com'>
print(m.group())
# aaa@xxx.com, bbb@yyy.com
នេះ? បន្ទាប់ពីវានឹងមានលទ្ធផលក្នុងការប្រកួតតិចតួចបំផុតដែលមិនលោភលន់ ដោយត្រូវគ្នានឹងខ្សែខ្លីដែលអាចធ្វើទៅបាន។
*?
+?
??
m = re.match(r'.+?com', s)
print(m)
# <re.Match object; span=(0, 11), match='aaa@xxx.com'>
print(m.group())
# aaa@xxx.com
ចំណាំថាការផ្គូផ្គងលោភលន់លំនាំដើមអាចត្រូវគ្នានឹងខ្សែអក្សរដែលមិនបានរំពឹងទុក។