Normal ifadenin içinde bir değişken nasıl kullanılır?


235

Bir variableiçeride kullanmak istiyorum regex, bunu nasıl yapabilirim Python?

TEXTO = sys.argv[1]

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

9
Dize birleştirme kullanıyorsunuz
— Chris Eberle

Yanıtlar:


52

3.6 python'dan Literal String Interpolation , "f-string" kullanabilirsiniz. Özel durumunuzda çözüm şöyle olacaktır:

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

DÜZENLE:

Yorumda, özel karakterlerle nasıl başa çıkılacağı konusunda bazı sorular olduğundan, cevabımı uzatmak istiyorum:

ham dizeler ('r'):

Normal ifadelerde özel karakterlerle uğraşırken anlamanız gereken ana kavramlardan biri, dizgi değişmezleri ile normal ifadenin kendisini ayırt etmektir. Çok iyi açıklanmıştır burada :

Kısacası:

Dize ile eşleştikten \bsonra bir kelime sınırı bulmak yerine diyelim . Yazmanız gerekenler:TEXTO\boundary

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

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

Bu yalnızca ham dize kullandığımız için işe yarar (regex'in önünde 'r' bulunur), aksi takdirde normalde (\ backsplashes) "\\\\ sınır" yazmamız gerekir. Ayrıca, '\ r' olmadan, \ b 'artık bir kelime sınırına değil, bir geri döneme dönüştürülecekti!

yeniden görünüm :

Temel olarak herhangi bir özel karakterin önüne bir geri boşluk koyar. Bu nedenle, TEXTO'da özel bir karakter bekliyorsanız, şunları yazmanız gerekir:

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

NOT: Herhangi bir sürümü için> = piton 3.7: !, ", %, ', ,, /, :, ;, <, =, >, @, ve `vardır kaçmamış. Yalnızca normal ifadede anlam taşıyan özel karakterler kaçmaya devam eder. _Python 3.3 beri kaçmış değildir. (s. Burada )

Kıvırcık parantez:

Eğer f-stringleri kullanarak normal ifade içinde niceleyiciler kullanmak istiyorsanız, çift kıvırcık parantez kullanmanız gerekir. Diyelim ki TEXTO ile tam olarak 2 rakam eşleştirmek istiyorsunuz:

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

2
2020 itibariyle, bu, normal bir ifade içinde bir değişkeni kullanmanın en basit ve en pitonik yoludur
— CONvid19

3
Bu kesinlikle bir WOW .
— Jason Goal

2
birisi burada "rf" önemini açıklayabilir
— Harsha Reddy

1
@HarshaReddy: 'r': Bu dize ham bir dizedir: Eğer kullanmazsanız, '\ b' geri silme karakterine dönüştürülür ( docs.python.org/3/howto/regex.html#more- desen gücü ). 'f' python'a bunun bir 'f-string' olduğunu söyler, s. Yukarıdaki bağlantıyı ve değişkeni kıvırcık parantezlere yazmanızı sağlar
— havadan

2
F-dizelerinde niceleyiciler nasıl yazılır: fr"foo{{1,5}}"(parantezleri ikiye
— katlayın

281

Normal ifadeyi bir dize olarak oluşturmanız gerekir:

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

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

Kullanımına dikkat re.escapemetin özel karakterler varsa, bunlar gibi yorumlanamaz böylece.


4
Değişken önce gelirse ne olur? r'' + foo + 'bar'?
— deed02392

@ deed02392 r''yapmanıza gerek yok re.escape(foo), yine de yapmanız gereken. Aslında, reönek olsun rya da olmasın , unicode dize olarak verilenleri yorumlar .
— OJFord

.Format () yöntemi de re.escape yerine çalışıyor mu veya re.escape () gerekli mi?
— Praxiteles

@praxiteles cevabı buldunuz mu?
— CONvid19

2
Bu çalışır eğer emin değilim hangi değişkenin bir parçası olduğu bir grup olması gerekir. Aşağıdaki diğer cevaplar bunun için daha sezgisel görünüyor ve normal ifadeyi birkaç ifadeye bölmeyin.
— guival

48
if re.search(r"\b(?<=\w)%s\b(?!\w)" % TEXTO, subject, re.IGNORECASE):

Bu, TEXTO'da bulunanları normal dizeye dize olarak ekler.



6

Birden çok küçük deseni bir araya getirerek düzenli bir ifade deseni oluşturmayı çok uygun buluyorum.

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)

Çıktı:

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

4

Yukarıdakilerin tümüne katılıyorum:

sys.argv[1] gibi bir şeydi Chicken\d{2}-\d{2}An\s*important\s*anchor

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

kullanmak istemezsiniz re.escape, çünkü bu durumda bir normal ifade gibi davranmasını istersiniz

TEXTO = sys.argv[1]

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

2

Birbirine benzeyen kullanıcı adlarını aramam gerekiyordu ve Ned Batchelder'in söyledikleri inanılmaz yardımcı oldu. Ancak, yeniden arama terimi oluşturmak için re.compile kullandığımda temiz çıktı vardı bulundu:

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

Çıktı aşağıdakiler kullanılarak yazdırılabilir:

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.

1

formatdilbilgisi suger kullanarak başka bir kullanım deneyebilirsiniz :

re_genre = r'{}'.format(your_variable)
regex_pattern = re.compile(re_genre)  

0

Bunun için format anahtar sözcüğünü de kullanabilirsiniz. Format yöntemi, {} yer tutucusunu bağımsız değişken olarak format yöntemine ilettiğiniz değişkenle değiştirir.

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

0

daha fazla örnek

Akış dosyaları ile configus.yml var

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

kullandığım python kodunda

data_time_real_file=re.findall(r""+flows[flow]["pattern"][0]+"", latest_file)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.