การแสดงออกปกติกรณีตายโดยไม่ต้อง re.compile?


331

ใน Python ฉันสามารถคอมไพล์นิพจน์ทั่วไปเพื่อให้ตรงตามตัวพิมพ์เล็กและใหญ่ได้โดยใช้re.compile:

>>> s = 'TeSt'
>>> casesensitive = re.compile('test')
>>> ignorecase = re.compile('test', re.IGNORECASE)
>>> 
>>> print casesensitive.match(s)
None
>>> print ignorecase.match(s)
<_sre.SRE_Match object at 0x02F0B608>

มีวิธีการทำเช่นเดียวกัน re.compileแต่ไม่ต้องใช้ ฉันไม่พบสิ่งใด ๆ เช่นiส่วนต่อท้ายของ Perl (เช่นm/test/i) ในเอกสารประกอบ


1
คุณสามารถหาข้อมูลเบื้องต้นเกี่ยวกับ Experssoins ที่ยอดเยี่ยมได้ที่: python-course.eu/re.php
2Obe

คำตอบ:


562

ผ่านre.IGNORECASEไปยังflagsพารามิเตอร์ของsearch, matchหรือsub:

re.search('test', 'TeSt', re.IGNORECASE)
re.match('test', 'TeSt', re.IGNORECASE)
re.sub('test', 'xxxx', 'Testing', flags=re.IGNORECASE)

2
re.match('test', 'TeSt', re.IGNORECASE)อาจนำไปสู่เมื่อทั้งสองของการเป็นแอตทริบิวต์TypeError Noneการใช้try & exceptเพื่อจับTypeErrorคู่โดย first_string == second_string โค้ดตัวอย่างรหัสการ def equal_ignore_case(first_string, second_string): try: return re.match(first_string, second_string, re.IGNORECASE) is not None except (AttributeError, TypeError): return first_string == second_string สาธิต
Abhijeet

3
@Abhijeet คุณไม่ควรใช้ลอง / ยกเว้นในกรณีนั้น เพียงตรวจสอบว่ามีสตริงใดเป็นNoneอันดับแรก
erb

มันเป็นสิ่งสำคัญที่จะใช้อาร์กิวเมนต์ชื่อflagsสำหรับre.subมิฉะนั้นมันผ่านre.IGNORECASEไปcountอาร์กิวเมนต์ (s ยัง. stackoverflow.com/questions/42581/... )
L3n95

101

คุณสามารถทำการค้นหาแบบตัวเล็กและตัวพิมพ์เล็กโดยใช้การค้นหา / การจับคู่โดยไม่ต้องตั้งค่าสถานะ IGNORECASE (ทดสอบใน Python 2.7.3):

re.search(r'(?i)test', 'TeSt').group()    ## returns 'TeSt'
re.match(r'(?i)test', 'TeSt').group()     ## returns 'TeSt'

2
เอกสารไม่ได้กล่าวถึงคุณสมบัติที่เพิ่มเข้ามาในเวอร์ชั่นเฉพาะใด ๆ (ตรงข้ามกับที่บอกว่า(?(condition)yes|no)มันถูกเพิ่มเข้ามาใน 2.4) ดังนั้นฉันคาดว่ามันจะมีให้ใช้งานได้ตลอดตั้งแต่รุ่นแรกของreโมดูลซึ่งฉันคิดว่าถูกเพิ่มเข้ามา ใน 1.5 โดยทั่วไปตั้งแต่จุดเริ่มต้นของเวลาสำหรับเจตนาและวัตถุประสงค์ทั้งหมดเมื่อมันมาถึง Python มีการบันทึกไว้ประมาณครึ่งทางผ่านส่วนแรกของหน้านี้: docs.python.org/2/library/re.html#regular-expression-syntax
ArtOfWarfare

4
ที่นี่เราไป - ฉันดูเอกสาร 1.5 และพบว่าเอกสารประมาณ 60% ของทางลงหน้านี้: docs.python.org/release/1.5/lib/ ......ฉันตรวจสอบเอกสาร 1.4 ซึ่งไม่ได้พูดถึง ฟีเจอร์นี้ ดังนั้นฉันจึงคิดว่ามันถูกเพิ่มเข้ามาใน 1.5 เมื่อregexโมดูลถูกคัดค้านreโมดูล
ArtOfWarfare

3
นี่เป็นวิธีแก้ปัญหาที่ดีเนื่องจากไม่ต้องการแฟล็ก ในกรณีของฉันฉันกำลังจัดเก็บสตริงการค้นหาใน Redis และสิ่งนี้มีประโยชน์จริง ๆ
ส่วนตัว

3
@Private: โดยหลักการแล้วมันตั้งค่าสถานะ re.I บนregex ทั้งหมด - ไม่ใช่เฉพาะกลุ่มการดักจับที่อยู่ข้างหน้า ระวังที่re.match(r'''A ((?i)B) C''', "a b c").group(0)ทำให้การจับคู่แบบตัวพิมพ์เล็กและตัวพิมพ์เล็ก (ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่) ไม่ได้อยู่ที่ B เท่านั้น! หากคุณต้องการจับคู่ตัวพิมพ์เล็กและใหญ่เฉพาะกลุ่มการจับภาพนี่ไม่ใช่ Droid ที่คุณต้องการ
smci

1
@ ส่วนตัว: ใช่เลย ประเด็นของฉันคือในความคิดมันเหมือนกับการตั้งค่าสถานะ ใน regex ทั้งหมด แม้แต่กลุ่มที่นำหน้ามัน (!) ไม่มีไวยากรณ์ที่จะพูดว่า "case-insensitive บนกลุ่มการดักจับต่อไปนี้เท่านั้น"
smci

53

เครื่องหมายตัวพิมพ์เล็กและตัวพิมพ์ใหญ่(?i)สามารถรวมเข้ากับรูปแบบ regex ได้โดยตรง:

>>> import re
>>> s = 'This is one Test, another TEST, and another test.'
>>> re.findall('(?i)test', s)
['Test', 'TEST', 'test']

2
ตัวเลือกที่ดีกว่าทำให้การพกพา regex ข้ามแพลตฟอร์มและเจตนาชัดเจนตามประกาศ
Sina Madani

1
นี้'(?i)'วิธีการยังมีประโยชน์ที่คุณสามารถสร้างรายชื่อของ regexp แล้วมีบางส่วนที่เป็นกรณีตายและบางคนไม่ (และแน่นอนคุณสามารถแมปre.compileผ่านรายการนั้นได้หากคุณต้องการ)
ไม่ใช่แค่

@SinaMadani ฉันสับสน เป็นวิธีที่พกพาได้มากกว่าflags=re.IGNORECASE?
Romain Vincent

10

คุณยังสามารถกำหนดตัวพิมพ์เล็กและตัวพิมพ์เล็กในระหว่างการคอมไพล์รูปแบบ:

pattern = re.compile('FIle:/+(.*)', re.IGNORECASE)

5
ในคำถาม OP ใช้สิ่งนี้และถามว่ามีวิธีอื่นอีกหรือไม่
Peter Wood

6
มีประโยชน์สำหรับวัตถุที่เลื่อนอย่างรวดเร็ว
stevek

6

ในการนำเข้า

import re

ในการประมวลผลรันไทม์:

RE_TEST = r'test'
if re.match(RE_TEST, 'TeSt', re.IGNORECASE):

ควรกล่าวว่าการไม่ใช้งานre.compileนั้นสิ้นเปลือง ทุกครั้งที่มีการเรียกใช้วิธีการจับคู่ข้างต้นนิพจน์ทั่วไปจะถูกรวบรวม นี่เป็นข้อปฏิบัติที่ผิดพลาดในภาษาการเขียนโปรแกรมอื่น ด้านล่างเป็นแนวปฏิบัติที่ดีกว่า

ในการเริ่มต้นแอพ:

self.RE_TEST = re.compile('test', re.IGNORECASE)

ในการประมวลผลรันไทม์:

if self.RE_TEST.match('TeSt'):

1
ขอบคุณ! ไม่มีใครพูดถึงการคอมไพล์ แต่เป็นตัวเลือกที่ฉลาดที่สุด!
StefanJCollier

2
OP ขอวิธีการแก้ปัญหาที่ไม่ได้ใช้re.compile()....
wpercy

4
#'re.IGNORECASE' for case insensitive results short form re.I
#'re.match' returns the first match located from the start of the string. 
#'re.search' returns location of the where the match is found 
#'re.compile' creates a regex object that can be used for multiple matches

 >>> s = r'TeSt'   
 >>> print (re.match(s, r'test123', re.I))
 <_sre.SRE_Match object; span=(0, 4), match='test'>
 # OR
 >>> pattern = re.compile(s, re.I)
 >>> print(pattern.match(r'test123'))
 <_sre.SRE_Match object; span=(0, 4), match='test'>

4

เมื่อต้องการดำเนินการที่ไม่คำนึงถึงขนาดตัวพิมพ์ให้จัดหา re.IGNORECASE

>>> import re
>>> test = 'UPPER TEXT, lower text, Mixed Text'
>>> re.findall('text', test, flags=re.IGNORECASE)
['TEXT', 'text', 'Text']

และถ้าเราต้องการแทนที่ข้อความที่ตรงกับตัวพิมพ์ใหญ่และเล็ก ...

>>> def matchcase(word):
        def replace(m):
            text = m.group()
            if text.isupper():
                return word.upper()
            elif text.islower():
                return word.lower()
            elif text[0].isupper():
                return word.capitalize()
            else:
                return word
        return replace

>>> re.sub('text', matchcase('word'), test, flags=re.IGNORECASE)
'UPPER WORD, lower word, Mixed Word'

1

หากคุณต้องการแทนที่ แต่ยังคงรักษาสไตล์ของ str ก่อนหน้า มันเป็นไปได้.

ตัวอย่างเช่น: ไฮไลต์สตริง "test asdasd TEST asd tEst asdasd"

sentence = "test asdasd TEST asd tEst asdasd"
result = re.sub(
  '(test)', 
  r'<b>\1</b>',  # \1 here indicates first matching group.
  sentence, 
  flags=re.IGNORECASE)

ทดสอบ asdasd TEST asd tEst asdasd


0

สำหรับนิพจน์ทั่วไปที่ไม่สนใจ case (Regex): มีสองวิธีในการเพิ่มโค้ดของคุณ:

  1. flags=re.IGNORECASE

    Regx3GList = re.search("(WCDMA:)((\d*)(,?))*", txt, **re.IGNORECASE**)
  2. เครื่องหมายตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ (?i)

    Regx3GList = re.search("**(?i)**(WCDMA:)((\d*)(,?))*", txt)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.