วิธีการใช้ตัวแปรภายในนิพจน์ปกติ?


235

ฉันต้องการใช้สิ่งvariableภายในregexฉันจะทำสิ่งนี้ได้Pythonอย่างไร

TEXTO = sys.argv[1]

if re.search(r"\b(?=\w)TEXTO\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

9
คุณใช้การต่อสายอักขระ
Chris Eberle

คำตอบ:


52

จากไพ ธ อน 3.6 คุณสามารถใช้การแก้ไขสตริงตัวอักษร "f-strings" ในกรณีเฉพาะของคุณการแก้ปัญหาจะเป็น:

if re.search(rf"\b(?=\w){TEXTO}\b(?!\w)", subject, re.IGNORECASE):
    ...do something

แก้ไข:

เนื่องจากมีคำถามในความคิดเห็นเกี่ยวกับวิธีจัดการกับตัวละครพิเศษฉันต้องการขยายคำตอบของฉัน:

สตริงดิบ ('r'):

หนึ่งในแนวคิดหลักที่คุณต้องเข้าใจเมื่อจัดการกับอักขระพิเศษในนิพจน์ทั่วไปคือการแยกแยะระหว่างตัวอักษรสตริงและนิพจน์ทั่วไป มันอธิบายได้ดีมากที่นี่ :

ในระยะสั้น:

สมมติว่าแทนการหาขอบเขตของคำ\bหลังจากที่คุณต้องการเพื่อให้ตรงกับสตริงTEXTO \boundaryคุณต้องเขียน:

TEXTO = "Var"
subject = r"Var\boundary"

if re.search(rf"\b(?=\w){TEXTO}\\boundary(?!\w)", subject, re.IGNORECASE):
    print("match")

ใช้งานได้เพียงเพราะเราใช้ raw-string (regex นำหน้าด้วย 'r') มิฉะนั้นเราจะต้องเขียน "\\\\ ขอบเขต" ใน regex (แบ็กสแลชสี่อัน) นอกจากนี้หากไม่มี '\ r', \ b 'จะไม่แปลงเป็นคำอีกต่อไป แต่เป็น backspace!

re.escape :

โดยทั่วไปจะใส่ Backspace ไว้ด้านหน้าอักขระพิเศษ ดังนั้นหากคุณคาดหวังอักขระพิเศษใน TEXTO คุณต้องเขียน:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

หมายเหตุ: สำหรับรุ่นใด ๆ > = 3.7 หลาม: !, ", %, ', ,, /, :, ;, <, =, >, @และ`จะไม่หนี เฉพาะอักขระพิเศษที่มีความหมายใน regex เท่านั้นที่ยังคงใช้การได้ _ไม่ได้หลบหนีตั้งแต่ Python 3.3 (s. ที่นี่ )

วงเล็บปีกกา:

หากคุณต้องการใช้ปริมาณภายในนิพจน์ปกติโดยใช้สตริง -f คุณต้องใช้เครื่องหมายปีกกาคู่ สมมติว่าคุณต้องการจับคู่ TEXTO แล้วตามด้วยตัวเลข 2 หลัก:

if re.search(rf"\b(?=\w){re.escape(TEXTO)}\d{{2}}\b(?!\w)", subject, re.IGNORECASE):
    print("match")

2
ตั้งแต่ปี 2020 นี่เป็นวิธีที่ง่ายและรวดเร็วที่สุดในการใช้ตัวแปรภายในนิพจน์ทั่วไป
CONVid19

3
นี้แน่นอนว้าว
Jason Goal

2
บางคนสามารถอธิบายความสำคัญของ "rf" ได้ที่นี่
Harsha Reddy

1
@HarshaReddy: 'r': สตริงนี้เป็นสตริงดิบ: หากคุณไม่ได้ใช้งาน '\ b' จะถูกแปลงเป็นอักขระ backspace ( docs.python.org/3/howto/regex.html#more- รูปแบบพลังงาน ) 'f' บอก python ว่านี่คือ 'f-string' ลิงก์ด้านบนและช่วยให้คุณสามารถเขียนตัวแปรลงในวงเล็บปีกกา
airborne

2
วิธีการเขียนปริมาณใน f- สตริง: fr"foo{{1,5}}"(วงเล็บสองครั้ง)
PunchyRascal

281

คุณต้องสร้าง regex เป็นสตริง:

TEXTO = sys.argv[1]
my_regex = r"\b(?=\w)" + re.escape(TEXTO) + r"\b(?!\w)"

if re.search(my_regex, subject, re.IGNORECASE):
    etc.

สังเกตการใช้งานre.escapeเพื่อที่ว่าหากข้อความของคุณมีอักขระพิเศษพวกเขาจะไม่ถูกตีความเช่นนั้น


4
เกิดอะไรขึ้นถ้าตัวแปรของคุณไปก่อน r'' + foo + 'bar'?
deed02392

@ deed02392 r''ไม่จำเป็นถ้าคุณทำre.escape(foo)ซึ่งคุณควรจะทำต่อไป ที่จริงแล้วฉันคิดว่าreตีความอะไรก็ตามที่มันได้รับเป็นยูนิโค้ดสตริงโดยไม่คำนึงว่าคุณจะใส่คำนำหน้าrหรือไม่
OJFord

.format () ทำงานได้ดีในตำแหน่ง re.escape หรือ re.escape () จำเป็นหรือไม่
Praxiteles

@praxiteles คุณพบคำตอบหรือไม่
CONVID19 19

2
ฉันไม่แน่ใจว่าสิ่งนี้ใช้ได้ผลหรือไม่ฉันต้องมีกลุ่มที่เป็นส่วนหนึ่งของตัวแปร คำตอบอื่น ๆ ด้านล่างดูเป็นธรรมชาติมากขึ้นสำหรับสิ่งนั้นและอย่าแยก regex ออกเป็นหลายนิพจน์
guival



6

ฉันคิดว่ามันสะดวกมากที่จะสร้างรูปแบบนิพจน์ปกติ

import re

string = "begin:id1:tag:middl:id2:tag:id3:end"
re_str1 = r'(?<=(\S{5})):'
re_str2 = r'(id\d+):(?=tag:)'
re_pattern = re.compile(re_str1 + re_str2)
match = re_pattern.findall(string)
print(match)

เอาท์พุท:

[('begin', 'id1'), ('middl', 'id2')]

4

ฉันเห็นด้วยทั้งหมดข้างต้นเว้นแต่:

sys.argv[1] เป็นสิ่งที่ต้องการ Chicken\d{2}-\d{2}An\s*important\s*anchor

sys.argv[1] = "Chicken\d{2}-\d{2}An\s*important\s*anchor"

คุณไม่ต้องการใช้re.escapeเพราะในกรณีนี้คุณต้องการให้มันทำงานเหมือน regex

TEXTO = sys.argv[1]

if re.search(r"\b(?<=\w)" + TEXTO + "\b(?!\w)", subject, re.IGNORECASE):
    # Successful match
else:
    # Match attempt failed

2

ฉันต้องการค้นหาชื่อผู้ใช้ที่คล้ายกันและสิ่งที่ Ned Batchelder กล่าวมีประโยชน์อย่างเหลือเชื่อ อย่างไรก็ตามฉันพบว่าฉันมีเอาต์พุตที่สะอาดกว่าเมื่อฉันใช้ re.compile เพื่อสร้างข้อความค้นหาใหม่:

pattern = re.compile(r"("+username+".*):(.*?):(.*?):(.*?):(.*)"
matches = re.findall(pattern, lines)

สามารถพิมพ์งานได้โดยใช้สิ่งต่อไปนี้:

print(matches[1]) # prints one whole matching line (in this case, the first line)
print(matches[1][3]) # prints the fourth character group (established with the parentheses in the regex statement) of the first line.


0

คุณสามารถใช้รูปแบบคำหลักเช่นกันสำหรับวิธีนี้รูปแบบจะแทนที่ {} ตัวยึดตำแหน่งเป็นตัวแปรที่คุณส่งผ่านไปยังวิธีการจัดรูปแบบเป็นอาร์กิวเมนต์

if re.search(r"\b(?=\w)**{}**\b(?!\w)".**format(TEXTO)**, subject, re.IGNORECASE):
    # Successful match**strong text**
else:
    # Match attempt failed

0

ตัวอย่างเพิ่มเติม

ฉันมี configus.yml พร้อมไฟล์ flow

"pattern":
  - _(\d{14})_
"datetime_string":
  - "%m%d%Y%H%M%f"

ในรหัสหลามฉันใช้

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.