Python 3 - นิพจน์ทั่วไป
แสดงออกปกติเป็นลำดับพิเศษของตัวละครที่จะช่วยให้คุณจับคู่หรือหาสายอื่น ๆ หรือชุดของสตริงโดยใช้ไวยากรณ์พิเศษที่จัดขึ้นในรูปแบบ นิพจน์ทั่วไปใช้กันอย่างแพร่หลายในโลก UNIX
โมดูล reให้การสนับสนุนอย่างเต็มที่สำหรับนิพจน์ทั่วไปเหมือน Perl ใน Python re โมดูลทำให้เกิดข้อยกเว้น re.error หากเกิดข้อผิดพลาดขณะคอมไพล์หรือใช้นิพจน์ทั่วไป
เราจะกล่าวถึงฟังก์ชันที่สำคัญสองอย่างซึ่งจะใช้ในการจัดการกับนิพจน์ทั่วไป อย่างไรก็ตามสิ่งเล็ก ๆ ก่อน: มีอักขระหลายตัวซึ่งจะมีความหมายพิเศษเมื่อใช้ในนิพจน์ทั่วไป เพื่อหลีกเลี่ยงความสับสนขณะจัดการกับนิพจน์ทั่วไปเราจะใช้ Raw Strings เป็นr'expression'.
รูปแบบพื้นฐานที่ตรงกับอักขระเดี่ยว
| ซีเนียร์ | นิพจน์และการจับคู่ | 
|---|---|
| 1 | a, X, 9, < อักขระธรรมดาก็ตรงกับตัวเองทุกประการ  | 
| 2 | . (a period) จับคู่อักขระเดี่ยวใด ๆ ยกเว้นขึ้นบรรทัดใหม่ '\ n'  | 
| 3 | \w จับคู่อักขระ "word": ตัวอักษรหรือตัวเลขหรือขีดล่าง [a-zA-Z0-9_]  | 
| 4 | \W จับคู่อักขระที่ไม่ใช่คำใด ๆ  | 
| 5 | \b ขอบเขตระหว่างคำและไม่ใช่คำ  | 
| 6 | \s จับคู่อักขระช่องว่างเดียว - เว้นวรรค, ขึ้นบรรทัดใหม่, ย้อนกลับ, แท็บ  | 
| 7 | \S จับคู่อักขระที่ไม่ใช่ช่องว่างใด ๆ  | 
| 8 | \t, \n, \r แท็บขึ้นบรรทัดใหม่ย้อนกลับ  | 
| 9 | \d เลขฐานสิบ [0-9]  | 
| 10 | ^ ตรงกับจุดเริ่มต้นของสตริง  | 
| 11 | $ จับคู่ส่วนท้ายของสตริง  | 
| 12 | \ ยับยั้ง "ความพิเศษ" ของตัวละคร  | 
แฟล็กการคอมไพล์
แฟล็กการคอมไพล์ช่วยให้คุณปรับเปลี่ยนลักษณะบางอย่างของการทำงานของนิพจน์ทั่วไป แฟล็กมีอยู่ในโมดูล re ภายใต้ชื่อสองชื่อชื่อยาวเช่นIGNORECASE และแบบอักษรตัวเดียวสั้น ๆ เช่น I
| ซีเนียร์ | ธงและความหมาย | 
|---|---|
| 1 | ASCII, A ทำให้หลาย Escape เช่น \ w, b, \ s และ \ d จับคู่กับอักขระ ASCII ที่มีคุณสมบัติตามลำดับเท่านั้น  | 
| 2 | DOTALL, S จับคู่อักขระใด ๆ รวมทั้งขึ้นบรรทัดใหม่  | 
| 3 | IGNORECASE, I ทำการจับคู่แบบไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่  | 
| 4 | LOCALE, L ทำการจับคู่ที่ทราบภาษา  | 
| 5 | MULTILINE, M การจับคู่หลายบรรทัดส่งผลต่อ ^ และ $  | 
| 6 | VERBOSE, X (for ‘extended’) เปิดใช้งาน REs แบบละเอียดซึ่งสามารถจัดระเบียบได้อย่างสะอาดตาและเข้าใจได้ง่ายขึ้น  | 
ฟังก์ชั่นการจับคู่
ฟังก์ชั่นนี้ความพยายามเพื่อให้ตรงกับ RE รูปแบบเพื่อสตริงที่มีตัวธง
นี่คือไวยากรณ์สำหรับฟังก์ชันนี้ -
re.match(pattern, string, flags = 0)
นี่คือคำอธิบายของพารามิเตอร์ -
| ซีเนียร์ | พารามิเตอร์และคำอธิบาย | 
|---|---|
| 1 | pattern นี่คือนิพจน์ทั่วไปที่จะจับคู่  | 
| 2 | string นี่คือสตริงซึ่งจะถูกค้นหาเพื่อให้ตรงกับรูปแบบที่จุดเริ่มต้นของสตริง  | 
| 3 | flags คุณสามารถระบุแฟล็กต่างๆโดยใช้บิตหรือ (|) นี่คือตัวดัดแปลงซึ่งแสดงอยู่ในตารางด้านล่าง  | 
re.matchผลตอบแทนที่ฟังก์ชั่นmatch คัดค้านความสำเร็จ Noneเมื่อล้มเหลว เราใช้ฟังก์ชันgroup (num)หรือgroups ()ของmatch วัตถุเพื่อให้ได้นิพจน์ที่ตรงกัน
| ซีเนียร์ | วิธีจับคู่วัตถุและคำอธิบาย | 
|---|---|
| 1 | group(num = 0) วิธีนี้ส่งคืนการจับคู่ทั้งหมด (หรือตัวเลขกลุ่มย่อยเฉพาะ)  | 
| 2 | groups() วิธีนี้จะส่งคืนกลุ่มย่อยที่ตรงกันทั้งหมดในทูเพิล (ว่างเปล่าถ้าไม่มี)  | 
ตัวอย่าง
#!/usr/bin/python3
import re
line = "Cats are smarter than dogs"
matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)
if matchObj:
   print ("matchObj.group() : ", matchObj.group())
   print ("matchObj.group(1) : ", matchObj.group(1))
   print ("matchObj.group(2) : ", matchObj.group(2))
else:
   print ("No match!!")
เมื่อดำเนินการโค้ดด้านบนจะให้ผลลัพธ์ดังนี้ -
matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter
ฟังก์ชันการค้นหา
นี้ฟังก์ชันการค้นหาเกิดขึ้นครั้งแรกของ RE รูปแบบภายในสตริงที่มีตัวธง
นี่คือไวยากรณ์สำหรับฟังก์ชันนี้ -
re.search(pattern, string, flags = 0)
นี่คือคำอธิบายของพารามิเตอร์ -
| ซีเนียร์ | พารามิเตอร์และคำอธิบาย | 
|---|---|
| 1 | pattern นี่คือนิพจน์ทั่วไปที่จะจับคู่  | 
| 2 | string นี่คือสตริงซึ่งจะถูกค้นหาเพื่อให้ตรงกับรูปแบบที่ใดก็ได้ในสตริง  | 
| 3 | flags คุณสามารถระบุแฟล็กต่างๆโดยใช้บิตหรือ (|) นี่คือตัวดัดแปลงซึ่งแสดงอยู่ในตารางด้านล่าง  | 
re.searchผลตอบแทนที่ฟังก์ชั่นmatch คัดค้านความสำเร็จ noneเมื่อล้มเหลว เราใช้ฟังก์ชันgroup (num)หรือgroups ()ของmatch วัตถุเพื่อให้ได้นิพจน์ที่ตรงกัน
| ซีเนียร์ | วิธีจับคู่วัตถุและคำอธิบาย | 
|---|---|
| 1 | group(num = 0) วิธีนี้ส่งคืนการจับคู่ทั้งหมด (หรือตัวเลขกลุ่มย่อยเฉพาะ)  | 
| 2 | groups() วิธีนี้จะส่งคืนกลุ่มย่อยที่ตรงกันทั้งหมดในทูเพิล (ว่างเปล่าถ้าไม่มี)  | 
ตัวอย่าง
#!/usr/bin/python3
import re
line = "Cats are smarter than dogs";
searchObj = re.search( r'(.*) are (.*?) .*', line, re.M|re.I)
if searchObj:
   print ("searchObj.group() : ", searchObj.group())
   print ("searchObj.group(1) : ", searchObj.group(1))
   print ("searchObj.group(2) : ", searchObj.group(2))
else:
   print ("Nothing found!!")
เมื่อดำเนินการโค้ดด้านบนจะให้ผลลัพธ์ดังนี้ -
matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter
การจับคู่กับการค้นหา
Python นำเสนอการดำเนินการดั้งเดิมสองแบบที่แตกต่างกันตามนิพจน์ทั่วไป: match ตรวจสอบการจับคู่เฉพาะที่จุดเริ่มต้นของสตริงในขณะที่ search ตรวจสอบการจับคู่ที่ใดก็ได้ในสตริง (นี่คือสิ่งที่ Perl ทำโดยค่าเริ่มต้น)
ตัวอย่าง
#!/usr/bin/python3
import re
line = "Cats are smarter than dogs";
matchObj = re.match( r'dogs', line, re.M|re.I)
if matchObj:
   print ("match --> matchObj.group() : ", matchObj.group())
else:
   print ("No match!!")
searchObj = re.search( r'dogs', line, re.M|re.I)
if searchObj:
   print ("search --> searchObj.group() : ", searchObj.group())
else:
   print ("Nothing found!!")
เมื่อดำเนินการโค้ดด้านบนจะให้ผลลัพธ์ดังนี้ -
No match!!
search --> matchObj.group() :  dogs
ค้นหาและแทนที่
ที่สำคัญที่สุดอย่างหนึ่ง re วิธีการที่ใช้นิพจน์ทั่วไปคือ sub.
ไวยากรณ์
re.sub(pattern, repl, string, max=0)
วิธีการนี้จะแทนที่เกิดขึ้นทั้งหมดของ RE รูปแบบในสตริงกับreplแทนเหตุการณ์ทั้งหมดเว้นแต่สูงสุดที่มีให้ วิธีนี้ส่งคืนสตริงที่แก้ไข
ตัวอย่าง
#!/usr/bin/python3
import re
phone = "2004-959-559 # This is Phone Number"
# Delete Python-style comments
num = re.sub(r'#.*$', "", phone)
print ("Phone Num : ", num)
# Remove anything other than digits
num = re.sub(r'\D', "", phone)    
print ("Phone Num : ", num)
เมื่อดำเนินการโค้ดด้านบนจะให้ผลลัพธ์ดังนี้ -
Phone Num :  2004-959-559
Phone Num :  2004959559
การปรับเปลี่ยนนิพจน์ทั่วไป: แฟล็กตัวเลือก
ลิเทอรัลนิพจน์ทั่วไปอาจรวมถึงโมดิฟายเออร์เสริมเพื่อควบคุมลักษณะต่างๆของการจับคู่ ตัวดัดแปลงถูกระบุเป็นแฟล็กทางเลือก คุณสามารถให้ตัวดัดแปลงหลายตัวโดยใช้เฉพาะ OR (|) ดังที่แสดงไว้ก่อนหน้านี้และอาจแสดงโดยหนึ่งในนั้น -
| ซีเนียร์ | ตัวปรับแต่งและคำอธิบาย | 
|---|---|
| 1 | re.I ทำการจับคู่แบบไม่คำนึงถึงขนาดตัวพิมพ์  | 
| 2 | re.L แปลความหมายของคำตามภาษาปัจจุบัน การตีความนี้มีผลต่อกลุ่มตัวอักษร (\ w และ \ W) รวมถึงพฤติกรรมขอบเขตคำ (\ b และ \ B)  | 
| 3 | re.M ทำให้ $ ตรงกับจุดสิ้นสุดของบรรทัด (ไม่ใช่แค่จุดสิ้นสุดของสตริง) และทำให้ ^ ตรงกับจุดเริ่มต้นของบรรทัดใด ๆ (ไม่ใช่แค่จุดเริ่มต้นของสตริง)  | 
| 4 | re.S ทำให้จุด (จุด) ตรงกับอักขระใด ๆ รวมถึงขึ้นบรรทัดใหม่  | 
| 5 | re.U ตีความตัวอักษรตามชุดอักขระ Unicode แฟล็กนี้มีผลต่อพฤติกรรมของ \ w, \ W, \ b, B  | 
| 6 | re.X อนุญาตให้ใช้ไวยากรณ์นิพจน์ทั่วไปที่ "น่ารักกว่า" โดยจะละเว้นช่องว่าง (ยกเว้นภายในชุด [] หรือเมื่อใช้เครื่องหมายแบ็กสแลชที่หลีกเลี่ยง) และถือว่า # ที่ไม่ใช้ Escape เป็นเครื่องหมายแสดงความคิดเห็น  | 
รูปแบบนิพจน์ทั่วไป
ยกเว้นอักขระควบคุม (+ ? . * ^ $ ( ) [ ] { } | \)อักขระทั้งหมดตรงกับตัวเอง คุณสามารถหลีกเลี่ยงอักขระควบคุมได้โดยนำหน้าด้วยแบ็กสแลช
ตารางต่อไปนี้แสดงรายการไวยากรณ์ของนิพจน์ทั่วไปที่มีอยู่ใน Python -
| ซีเนียร์ | พารามิเตอร์และคำอธิบาย | 
|---|---|
| 1 | ^ ตรงกับจุดเริ่มต้นของบรรทัด  | 
| 2 | $ ตรงกับจุดสิ้นสุดของบรรทัด  | 
| 3 | . จับคู่อักขระเดี่ยวใด ๆ ยกเว้นขึ้นบรรทัดใหม่ การใช้ตัวเลือก m ช่วยให้จับคู่ขึ้นบรรทัดใหม่ได้เช่นกัน  | 
| 4 | [...] จับคู่อักขระเดี่ยวใด ๆ ในวงเล็บ  | 
| 5 | [^...] จับคู่อักขระเดี่ยวใด ๆ ที่ไม่อยู่ในวงเล็บ  | 
| 6 | re* จับคู่ 0 หรือมากกว่าที่เกิดขึ้นของนิพจน์ก่อนหน้า  | 
| 7 | re+ จับคู่นิพจน์ก่อนหน้าอย่างน้อย 1 รายการ  | 
| 8 | re? จับคู่นิพจน์ที่อยู่ก่อนหน้า 0 หรือ 1 ครั้ง  | 
| 9 | re{ n} ตรงกับจำนวน n ของนิพจน์ที่เกิดขึ้นก่อนหน้า  | 
| 10 | re{ n,} จับคู่ n เหตุการณ์หรือมากกว่าที่เกิดขึ้นก่อนหน้า  | 
| 11 | re{ n, m} จับคู่อย่างน้อย n และมากที่สุด m ที่เกิดขึ้นของนิพจน์ก่อนหน้า  | 
| 12 | a|b จับคู่ a หรือ b  | 
| 13 | (re) จัดกลุ่มนิพจน์ทั่วไปและจดจำข้อความที่ตรงกัน  | 
| 14 | (?imx) สลับตัวเลือก i, m หรือ x ชั่วคราวภายในนิพจน์ทั่วไป หากอยู่ในวงเล็บจะมีผลเฉพาะพื้นที่นั้นเท่านั้น  | 
| 15 | (?-imx) ปิดตัวเลือก i, m หรือ x ชั่วคราวภายในนิพจน์ทั่วไป หากอยู่ในวงเล็บจะมีผลเฉพาะพื้นที่นั้นเท่านั้น  | 
| 16 | (?: re) จัดกลุ่มนิพจน์ทั่วไปโดยไม่จำข้อความที่ตรงกัน  | 
| 17 | (?imx: re) สลับตัวเลือก i, m หรือ x ชั่วคราวภายในวงเล็บ  | 
| 18 | (?-imx: re) ปิดตัวเลือก i, m หรือ x ชั่วคราวภายในวงเล็บ  | 
| 19 | (?#...) แสดงความคิดเห็น.  | 
| 20 | (?= re) ระบุตำแหน่งโดยใช้รูปแบบ ไม่มีช่วง  | 
| 21 | (?! re) ระบุตำแหน่งโดยใช้การปฏิเสธรูปแบบ ไม่มีช่วง  | 
| 22 | (?> re) จับคู่รูปแบบอิสระโดยไม่ต้องย้อนรอย  | 
| 23 | \w จับคู่อักขระคำ  | 
| 24 | \W จับคู่อักขระที่ไม่ใช่คำหลัก  | 
| 25 | \s ตรงกับช่องว่าง เทียบเท่ากับ [\ t \ n \ r \ f]  | 
| 26 | \S ตรงกับ nonwhitespace  | 
| 27 | \d ตรงกับตัวเลข เทียบเท่ากับ [0-9]  | 
| 28 | \D ตรงกับ nondigits  | 
| 29 | \A ตรงกับจุดเริ่มต้นของสตริง  | 
| 30 | \Z ตรงกับจุดสิ้นสุดของสตริง หากมีขึ้นบรรทัดใหม่จะตรงกับก่อนขึ้นบรรทัดใหม่  | 
| 31 | \z ตรงกับจุดสิ้นสุดของสตริง  | 
| 32 | \G ตรงกับจุดที่นัดสุดท้ายจบ  | 
| 33 | \b จับคู่ขอบเขตของคำเมื่ออยู่นอกวงเล็บ จับคู่ backspace (0x08) เมื่ออยู่ในวงเล็บ  | 
| 34 | \B ตรงกับขอบเขตที่ไม่ใช่คำ  | 
| 35 | \n, \t, etc. จับคู่การขึ้นบรรทัดใหม่การคืนค่าขนส่งแท็บ ฯลฯ  | 
| 36 | \1...\9 ตรงกับนิพจน์ย่อยที่จัดกลุ่มที่ n  | 
| 37 | \10 จับคู่นิพจน์ย่อยที่จัดกลุ่มที่ n ถ้าตรงกันแล้ว มิฉะนั้นหมายถึงการแทนค่าฐานแปดของรหัสอักขระ  | 
ตัวอย่างนิพจน์ทั่วไป
อักขระตามตัวอักษร
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | python ตรงกับ "python"  | 
คลาสตัวละคร
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | [Pp]ython จับคู่ "Python" หรือ "python"  | 
| 2 | rub[ye] จับคู่ "ทับทิม" หรือ "รูบ"  | 
| 3 | [aeiou] จับคู่สระตัวพิมพ์เล็กตัวใดตัวหนึ่ง  | 
| 4 | [0-9] จับคู่ตัวเลขใด ๆ เหมือนกับ [0123456789]  | 
| 5 | [a-z] จับคู่ตัวอักษร ASCII ตัวพิมพ์เล็ก  | 
| 6 | [A-Z] จับคู่ตัวอักษร ASCII ตัวพิมพ์ใหญ่ใด ๆ  | 
| 7 | [a-zA-Z0-9] ตรงกับข้อใด ๆ ข้างต้น  | 
| 8 | [^aeiou] จับคู่สิ่งอื่นที่ไม่ใช่สระตัวพิมพ์เล็ก  | 
| 9 | [^0-9] จับคู่สิ่งอื่นที่ไม่ใช่ตัวเลข  | 
คลาสตัวละครพิเศษ
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | . จับคู่อักขระใด ๆ ยกเว้นขึ้นบรรทัดใหม่  | 
| 2 | \d จับคู่ตัวเลข: [0-9]  | 
| 3 | \D จับคู่ nondigit: [^ 0-9]  | 
| 4 | \s จับคู่อักขระเว้นวรรค: [\ t \ r \ n \ f]  | 
| 5 | \S ตรงกับ nonwhitespace: [^ \ t \ r \ n \ f]  | 
| 6 | \w จับคู่อักขระคำเดียว: [A-Za-z0-9_]  | 
| 7 | \W จับคู่อักขระที่ไม่ใช่คำหลัก: [^ A-Za-z0-9_]  | 
กรณีการทำซ้ำ
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | ruby? จับคู่ "ถู" หรือ "ทับทิม": y เป็นทางเลือก  | 
| 2 | ruby* จับคู่ "ถู" บวก 0 หรือมากกว่า ys  | 
| 3 | ruby+ จับคู่ "ถู" บวก 1 ys ขึ้นไป  | 
| 4 | \d{3} จับคู่ 3 หลักทุกประการ  | 
| 5 | \d{3,} จับคู่ 3 หลักขึ้นไป  | 
| 6 | \d{3,5} จับคู่ 3, 4 หรือ 5 หลัก  | 
การทำซ้ำ Nongreedy
สิ่งนี้ตรงกับจำนวนการทำซ้ำน้อยที่สุด -
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | <.*> การทำซ้ำแบบโลภ: ตรงกับ "<python> perl>"  | 
| 2 | <.*?> Nongreedy: ตรงกับ "<python>" ใน "<python> perl>"  | 
การจัดกลุ่มด้วยวงเล็บ
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | \D\d+ ไม่มีกลุ่ม: + ซ้ำ \ d  | 
| 2 | (\D\d)+ จัดกลุ่ม: + ซ้ำ \ D \ d คู่  | 
| 3 | ([Pp]ython(,)?)+ จับคู่ "Python", "Python, python, python" ฯลฯ  | 
การอ้างอิงย้อนกลับ
สิ่งนี้จะจับคู่กลุ่มที่ตรงกันก่อนหน้านี้อีกครั้ง -
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | ([Pp])ython&\1ails จับคู่ python & pails หรือ Python & Pails  | 
| 2 | (['"])[^\1]*\1 สตริงเดี่ยวหรือคู่ \ 1 จับคู่กลุ่มแรกที่จับคู่ \ 2 ตรงกับกลุ่มที่ 2 ที่จับคู่ ฯลฯ  | 
ทางเลือก
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | python|perl จับคู่ "python" หรือ "perl"  | 
| 2 | rub(y|le) จับคู่ "ทับทิม" หรือ "รูเบิล"  | 
| 3 | Python(!+|\?) "Python" ตามด้วยอย่างน้อยหนึ่งตัว! หรือหนึ่ง?  | 
จุดยึด
สิ่งนี้จำเป็นต้องระบุตำแหน่งที่ตรงกัน
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | ^Python จับคู่ "Python" ที่จุดเริ่มต้นของสตริงหรือบรรทัดภายใน  | 
| 2 | Python$ จับคู่ "Python" ที่ส่วนท้ายของสตริงหรือบรรทัด  | 
| 3 | \APython จับคู่ "Python" ที่จุดเริ่มต้นของสตริง  | 
| 4 | Python\Z จับคู่ "Python" ที่ส่วนท้ายของสตริง  | 
| 5 | \bPython\b จับคู่ "Python" ที่ขอบเขตคำ  | 
| 6 | \brub\B \ B คือขอบเขตที่ไม่ใช่คำ: จับคู่ "rub" ใน "rube" และ "ruby" แต่ไม่ใช่เพียงอย่างเดียว  | 
| 7 | Python(?=!) จับคู่ "Python" หากตามด้วยเครื่องหมายอัศเจรีย์  | 
| 8 | Python(?!!) จับคู่ "Python" หากไม่ตามด้วยเครื่องหมายอัศเจรีย์  | 
ไวยากรณ์พิเศษพร้อมวงเล็บ
| ซีเนียร์ | ตัวอย่างและคำอธิบาย | 
|---|---|
| 1 | R(?#comment) ตรงกับ "R" ส่วนที่เหลือทั้งหมดเป็นความคิดเห็น  | 
| 2 | R(?i)uby ไม่คำนึงถึงตัวพิมพ์เล็กและใหญ่ขณะจับคู่ "uby"  | 
| 3 | R(?i:uby) เช่นเดียวกับด้านบน  | 
| 4 | rub(?:y|le)) จัดกลุ่มเท่านั้นโดยไม่ต้องสร้าง backreference \ 1  |