سؤال

ما هو الفرق بين search() و match() وظائف في بايثون re وحدة?

لقد قرأت توثيق (الوثائق الحالية)، ولكن يبدو أنني لا أتذكر ذلك أبدًا.وأظل مضطرًا للبحث عنه وإعادة تعلمه.آمل أن يجيبني شخص ما بشكل واضح مع الأمثلة حتى (ربما) ستظل عالقة في رأسي.أو على الأقل سيكون لدي مكان أفضل لأعود إليه بسؤالي وسيستغرق الأمر وقتًا أقل لإعادة تعلمه.

هل كانت مفيدة؟

المحلول

re.match يتم تثبيته في بداية السلسلة.هذا لا علاقة له بالأسطر الجديدة، لذا فهو ليس مثل الاستخدام ^ في النمط.

كما إعادة مطابقة الوثائق يقول:

إذا كان صفر أو أكثر من الأحرف في بداية السلسلة مطابقة نمط التعبير العادي ، وإرجاع ملف موافق MatchObject مثال.يعود None إذا لم تكن السلسلة تطابق النمطلاحظ أن هذا هو يختلف عن مباراة صفرية الطول.

ملحوظة:إذا كنت تريد تحديد موقع تطابق في أي مكان في السلسلة ، استخدم search()بدلاً من.

re.search يبحث في السلسلة بأكملها، كما تقول الوثائق:

المسح من خلال السلسلة تبحث عن الموقع حيث التعبير العادي ينتج النمط تطابقا ، ويعيد موافق MatchObject مثال.يعود None إذا لم يكن هناك منصب في سلسلة يطابق النمط ؛لاحظ أن هذا يختلف عن إيجاد مباراة صفرية الطول في مرحلة ما في خيط.

لذا، إذا كنت بحاجة إلى المطابقة في بداية السلسلة، أو لمطابقة السلسلة بأكملها، فاستخدمها match.إنه أسرع.وإلا استخدم search.

الوثائق لديها قسم خاص ل match ضد. search والذي يغطي أيضًا سلاسل متعددة الأسطر:

تقدم بايثون اثنين من البدائيات المختلفة العمليات على أساس منتظم التعابير: match الشيكات للمباراة فقط في البداية من الخيط، بينما search الشيكات للمباراة في أى مكان في السلسلة (هذا ما بيرل يفعل افتراضيا).

لاحظ أن match قد تختلف عن search حتى عند استخدام تعبير عادي بدءا من '^': '^' المباريات فقط في بداية السلسلة، أو في MULTILINE الوضع أيضا على الفور بعد سطر جديد.ال "match" نجاح العملية فقط إذا كان النمط يتطابق مع يبدأ من السلسلة بغض النظر عن الوضع ، أو في البداية الموقف الذي يعطيه اختياري pos حجة بغض النظر عما إذا كان خط جديد يسبقه.

الآن، ما يكفي من الكلام.حان الوقت لرؤية بعض الأمثلة على التعليمات البرمجية:

# example code:
string_with_newlines = """something
someotherthing"""

import re

print re.match('some', string_with_newlines) # matches
print re.match('someother', 
               string_with_newlines) # won't match
print re.match('^someother', string_with_newlines, 
               re.MULTILINE) # also won't match
print re.search('someother', 
                string_with_newlines) # finds something
print re.search('^someother', string_with_newlines, 
                re.MULTILINE) # also finds something

m = re.compile('thing$', re.MULTILINE)

print m.match(string_with_newlines) # no match
print m.match(string_with_newlines, pos=4) # matches
print m.search(string_with_newlines, 
               re.MULTILINE) # also matches

نصائح أخرى

وsearch ⇒ العثور على شيء في أي مكان في السلسلة والعودة كائن المباراة.

وmatch ⇒ العثور على شيء في بداية السلسلة وإرجاع كائن المباراة.

re.search يبحثواق للنمط في جميع أنحاء السلسلة, ، بينما re.match يفعل لا تبحث النمط؛وإذا لم تفعل ذلك، فليس لديها خيار آخر سوى القيام بذلك مباراة ذلك في بداية السلسلة.

ويمكنك الرجوع إلى المثال التالي لفهم عمل re.match وre.search

a = "123abc"
t = re.match("[a-z]+",a)
t = re.search("[a-z]+",a)

وre.match سيعود لا شيء، ولكن re.search سيعود اي بي سي.

والفرق هو، على re.match() يضلل أي شخص اعتاد على بيرل ، <م> البقرى ، أو <م> ااا التعبير العادية مطابقة، وre.search() لا . : في -)

وأكثر بوعي، وتصريحات جون D. كوك ، re.match() "يتصرف كما لو كان كل نمط لديها ^ إرفاق مسبقا ". وبعبارة أخرى، re.match('pattern') يساوي re.search('^pattern'). لذلك المراسي الجانب الأيسر نمط و. ولكنه أيضا <م> لا يرسو الجانب الأيمن نمطا من:. التي لا تزال تتطلب $ تنتهي

وبصراحة نظرا لأعلاه، أعتقد أنه يجب إهمال re.match(). وأود أن تكون مهتمة لمعرفة الأسباب التي ينبغي الاحتفاظ بها.

تعد المطابقة أسرع بكثير من البحث، لذلك بدلاً من إجراء regex.search("word")، يمكنك إجراء regex.match((.*?)word(.*?)) والحصول على الكثير من الأداء إذا كنت تعمل مع الملايين من عينات.

هذا التعليق من @ivan_bilan ضمن الإجابة المقبولة أعلاه جعلني أفكر إذا كان الأمر كذلك hack يعمل في الواقع على تسريع أي شيء، لذلك دعونا نتعرف على عدد أطنان الأداء التي ستكسبها حقًا.

لقد قمت بإعداد مجموعة الاختبار التالية:

import random
import re
import string
import time

LENGTH = 10
LIST_SIZE = 1000000

def generate_word():
    word = [random.choice(string.ascii_lowercase) for _ in range(LENGTH)]
    word = ''.join(word)
    return word

wordlist = [generate_word() for _ in range(LIST_SIZE)]

start = time.time()
[re.search('python', word) for word in wordlist]
print('search:', time.time() - start)

start = time.time()
[re.match('(.*?)python(.*?)', word) for word in wordlist]
print('match:', time.time() - start)

لقد أجريت 10 قياسات (1 مليون، 2 مليون، ...، 10 ملايين كلمة) مما أعطاني المخطط التالي:

match vs. search regex speedtest line plot

الخطوط الناتجة تكون مستقيمة بشكل مدهش (في الواقع ليس من المستغرب).و ال search الوظيفة أسرع (قليلاً). نظرا لهذا المزيج من الأنماط المحددة.المغزى من هذا الاختبار: تجنب الإفراط في تحسين التعليمات البرمجية الخاصة بك.

محاولات re.match لمطابقة النمط في بداية السلسلة.يحاول re.search مطابقة النمط في جميع أنحاء السلسلة حتى يجد تطابقًا.

أقصر بكثير:

  • search بمسح الحوض الصغير سلسلة كاملة.

  • match هل بداية السلسلة فقط.

بعد السابق يقول ذلك:

>>> a = "123abc"
>>> re.match("[a-z]+",a)
None
>>> re.search("[a-z]+",a)
abc
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top