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.