وبلاگ رسانگار
با ما حرفه ای باشید

سرور مجازی NVMe

استفاده از Regex برای دستکاری متن در پایتون

0 34
زمان لازم برای مطالعه: 10 دقیقه


معرفی

پیش پردازش متن یکی از مهمترین وظایف در پردازش زبان طبیعی (NLP) است. به عنوان مثال، ممکن است بخواهید تمام علائم نگارشی را از اسناد متنی حذف کنید تا بتوان از آنها برای طبقه بندی متن استفاده کرد. به طور مشابه، ممکن است بخواهید اعداد را از یک رشته متن استخراج کنید. نوشتن اسکریپت های دستی برای چنین کارهای پیش پردازشی نیاز به تلاش زیادی دارد و مستعد خطا است. با توجه به اهمیت این وظایف پیش پردازش، عبارات با قاعده (معروف به Regex) به زبان های مختلف به منظور سهولت این وظایف پیش پردازش متن توسعه داده شده است.

یک عبارت منظم یک رشته متنی است که یک الگوی جستجو را توصیف می کند که می تواند برای مطابقت یا جایگزینی الگوهای داخل یک رشته با حداقل مقدار کد مورد استفاده قرار گیرد. در این آموزش انواع مختلف عبارات منظم را در زبان پایتون پیاده سازی می کنیم.

برای پیاده سازی عبارات منظم، Python’s re بسته قابل استفاده است. پایتون را وارد کنید re بسته با دستور زیر:

import re

جستجوی الگوها در یک رشته

یکی از رایج ترین کارهای NLP این است که جستجو کنید آیا یک رشته دارای الگوی خاصی است یا خیر. به عنوان مثال، ممکن است بخواهید عملیاتی را انجام دهید روی بر اساس رشته روی شرطی که رشته شامل یک عدد باشد.

برای جستجوی یک الگو در یک رشته، match و findall عملکرد از re بسته استفاده می شود.

عملکرد مسابقه

مقدار دهی اولیه یک متغیر text با یک رشته متن به صورت زیر:

text = "The film Titanic was released in 1998"

بیایید یک عبارت regex بنویسیم که با یک رشته با هر طول و هر کاراکتری مطابقت داشته باشد:

result = re.match(r".*", text)

اولین پارامتر از match تابع عبارت regex است که می خواهید جستجو کنید. عبارت Regex با حروف الفبا شروع می شود r به دنبال الگویی که می خواهید جستجو کنید. الگو باید مانند هر رشته دیگری در گیومه های تک یا دوتایی محصور شود.

عبارت regex بالا با رشته متن مطابقت دارد، زیرا ما سعی می کنیم رشته ای با هر طول و هر کاراکتری را مطابقت دهیم. اگر یک مسابقه پیدا شد، match تابع برمی گردد _sre.SRE_Match شیء مطابق شکل زیر:

type(result)

خروجی:

_sre.SRE_Match

اکنون برای یافتن رشته منطبق، می توانید از دستور زیر استفاده کنید:

result.group(0)

خروجی:

'The film Titanic was released in 1998'

در صورتی که هیچ مطابقی توسط match عملکرد، الف null شی برگردانده می شود.

اکنون عبارت regex قبلی با یک رشته با هر طول و هر کاراکتری مطابقت دارد. همچنین با یک رشته خالی به طول صفر مطابقت دارد. برای آزمایش این، مقدار متغیر متن را با یک رشته خالی به روز کنید:

text = ""

حال، اگر دوباره عبارت regex زیر را اجرا کنید، مطابقت پیدا می‌شود:

result = re.match(r".*", text)

از آنجایی که ما تعیین کردیم که رشته را با هر طول و هر کاراکتری مطابقت دهیم، حتی یک رشته خالی هم مطابقت دارد.

برای تطبیق رشته ای با طول حداقل 1، از عبارت regex زیر استفاده می شود:

result = re.match(r".+", text)

در اینجا علامت مثبت مشخص می کند که رشته باید حداقل یک کاراکتر داشته باشد.

جستجو در حروف الفبا

را match تابع را می توان برای یافتن هر حروف الفبای درون یک رشته استفاده کرد. بیایید متغیر متن را با متن زیر مقداردهی اولیه کنیم:

text = "The film Titanic was released in 1998"

اکنون برای یافتن تمام حروف الفبا، چه بزرگ و چه کوچک، می توانیم از عبارت regex زیر استفاده کنیم:

result = re.match(r"(a-zA-z)+", text)

این عبارت regex بیان می کند که با رشته متن برای هر حروف کوچکی مطابقت دارد a به کوچک z یا سرمایه A به سرمایه Z. علامت مثبت مشخص می کند که رشته باید حداقل یک کاراکتر داشته باشد. اجازه دهید print مطابقت یافت شده توسط عبارت بالا:

print(result.group(0))

خروجی:

The

در خروجی می بینید که کلمه اول ie The برگردانده می شود. این به این دلیل است که match تابع فقط اولین تطابق یافت شده را برمی گرداند. در regex مشخص کردیم که الگوها را با الفبای کوچک و بزرگ پیدا کنید a به z. اولین مسابقه یافت شده بود The. بعد از کلمه The یک فاصله وجود دارد که به عنوان یک حرف الفبا در نظر گرفته نمی شود، بنابراین تطبیق متوقف شد و عبارت فقط برگردانده شد The، که اولین مسابقه است.

با این حال، یک مشکل در این مورد وجود دارد. اگر رشته ای به جای الفبا با عدد شروع شود، match حتی اگر حروف بعد از عدد وجود داشته باشد، تابع صفر خواهد شد. بیایید این را در عمل ببینیم:

text = "1998 was the year when the film titanic was released"
result = re.match(r"(a-zA-z)+", text)
type(result)

خروجی:

NoneType

در اسکریپت بالا متغیر متن را به روز کرده ایم و اکنون با یک رقم شروع می شود. ما سپس استفاده کردیم match عملکرد جستجوی حروف الفبا در رشته. اگرچه رشته متن حاوی حروف الفبا است، از آن زمان null برگردانده می شود match تابع فقط با اولین عنصر در رشته مطابقت دارد.

برای حل این مشکل می توانیم از search تابع.

تابع جستجو

را search تابع مشابه است match تابع یعنی سعی می کند با الگوی مشخص شده مطابقت داشته باشد. با این حال، بر خلاف match تابع، به جای تطبیق تنها با عنصر اول، الگو را در سطح جهانی مطابقت می دهد. بنابراین، search تابع یک تطابق را برمی گرداند حتی اگر رشته حاوی الفبای ابتدای رشته نباشد اما در جای دیگری از رشته دارای الفبا باشد، همانطور که در زیر نشان داده شده است:

text = "1998 was the year when the film titanic was released"
result = re.search(r"(a-zA-z)+", text)
print(result.group(0))

خروجی:

was

را search تابع “بود” را برمی گرداند زیرا این اولین تطابق است که در رشته متن یافت می شود.

رشته تطبیق از ابتدا

برای بررسی اینکه آیا یک رشته با یک کلمه خاص شروع می شود، می توانید از کلید هویج استفاده کنید ^ به دنبال آن کلمه مطابقت با search مطابق شکل زیر عمل کنید. فرض کنید رشته زیر را داریم:

text = "XYZ 1998 was the year when the film titanic was released"

اگر بخواهیم بفهمیم که آیا رشته با “1998” شروع می شود، می توانیم از آن استفاده کنیم search عملکرد به شرح زیر است:

result = re.search(r"^1998", text)
type(result)

در خروجی، null از آنجایی که رشته متنی در ابتدا حاوی “1998” نیست، بازگردانده خواهد شد.

حالا بیایید متغیر متن محتوا را تغییر دهیم و “1998” را در ابتدا اضافه کنیم و سپس بررسی کنیم که آیا “1998” در ابتدا پیدا شده است یا خیر. اسکریپت زیر را اجرا کنید:

text = "1998 was the year when the film titanic was released"
if re.search(r"^1998", text):
    print("Match found")
else:
    print("Match not found")

خروجی:

Match found

تطبیق رشته ها از انتها

برای بررسی اینکه آیا یک رشته به پایان می رسد با یک کلمه خاص یا نه، می توانیم از کلمه در عبارت منظم و به دنبال آن علامت دلار استفاده کنیم. علامت دلار پایان بیانیه را نشان می دهد. به مثال زیر دقت کنید:

text = "1998 was the year when the film titanic was released"
if re.search(r"1998$", text):
    print("Match found")
else:
    print("Match not found")

در اسکریپت بالا سعی کردیم بفهمیم که آیا رشته متن با “1998” ختم می شود یا خیر، که اینطور نیست.

خروجی:

Match not found

حال اگر رشته را به‌روزرسانی کنیم و «1998» را در انتهای رشته متن اضافه کنیم، اسکریپت فوق مطابق شکل زیر «Match found» را برمی‌گرداند:

text = "was the year when the film titanic was released 1998"
if re.search(r"1998$", text):
    print("Match found")
else:
    print("Match not found")

خروجی:

Match found

جایگزینی متن در یک رشته

تا به حال ما از regex برای یافتن اینکه آیا یک الگو در یک رشته وجود دارد یا خیر استفاده کرده ایم. بیایید با یک تابع regex پیشرفته دیگر به جلو حرکت کنیم، یعنی جایگزین کردن متن در یک رشته. را sub تابع برای این منظور استفاده می شود.

بیایید یک مثال ساده از تابع جایگزین بیاوریم. فرض کنید رشته زیر را داریم:

text = "The film Pulp Fiction was released in year 1994"

برای جایگزینی رشته “Pulp Fiction” با “Forrest Gump” (فیلم دیگری که در سال 1994 منتشر شد) می توانیم از sub عملکرد به شرح زیر است:

result = re.sub(r"Pulp Fiction", "Forrest Gump", text)

اولین پارامتر به sub تابع عبارت منظمی است که الگو را برای جایگزینی پیدا می کند. پارامتر دوم متن جدیدی است که می خواهید به عنوان جایگزینی برای متن قدیمی و پارامتر سوم رشته متن است. روی که عملیات جایگزین انجام خواهد شد.

اگر شما print متغیر نتیجه، رشته جدید را خواهید دید.

حالا بیایید تمام حروف الفبای رشته خود را با کاراکتر “X” جایگزین کنیم. اسکریپت زیر را اجرا کنید:

text = "The film Pulp Fiction was released in year 1994"
result = re.sub(r"(a-z)", "X", text)
print(result)

خروجی:

TXX XXXX PXXX FXXXXXX XXX XXXXXXXX XX XXXX 1994

از خروجی می توان فهمید که همه کاراکترها به جز بزرگ ها جایگزین شده اند. این به این دلیل است که ما مشخص کردیم a-z فقط و نه A-Z. دو راه برای حل این مشکل وجود دارد. شما هم می توانید مشخص کنید A-Z در عبارت منظم همراه با a-z به شرح زیر است:

result = re.sub(r"(a-zA-Z)", "X", text)

یا می توانید پارامتر اضافی را ارسال کنید flags به تابع sub و مقدار آن را بر روی re.I که به حروف بزرگ و کوچک اشاره دارد، به شرح زیر:

result = re.sub(r"(a-z)", "X", text, flags=re.I)

جزئیات بیشتر در مورد انواع مختلف پرچم ها را می توانید در Python regex پیدا کنید اسناد رسمی page.

کلاس های کاراکتر کوتاه نویسی

انواع مختلفی از کلاس‌های کاراکتر کوتاه‌نویسی وجود دارد که می‌توان از آنها برای انجام انواع مختلف توابع دستکاری رشته‌ها بدون نیاز به نوشتن منطق پیچیده استفاده کرد. در این بخش به برخی از آنها می پردازیم:

حذف ارقام از یک رشته

عبارت regex برای یافتن ارقام در یک رشته است \d. از این الگو می توان برای حذف ارقام از یک رشته با جایگزین کردن آنها با یک رشته خالی به طول صفر مانند شکل زیر استفاده کرد:

text = "The film Pulp Fiction was released in year 1994"
result = re.sub(r"\d", "", text)
print(result)

خروجی:

The film Pulp Fiction was released in year 

حذف حروف الفبا از رشته

text = "The film Pulp Fiction was released in year 1994"
result = re.sub(r"(a-z)", "", text, flags=re.I)
print(result)

خروجی:

1994

حذف کاراکترهای کلمه

اگر می خواهید تمام کاراکترهای کلمه (حروف و اعداد) را از یک رشته حذف کنید و کاراکترهای باقی مانده را حفظ کنید، می توانید از \w الگو را در regex خود قرار دهید و آن را با یک رشته خالی به طول صفر جایگزین کنید، همانطور که در زیر نشان داده شده است:

text = "The film, '@Pulp Fiction' was ? released in % $ year 1994."
result = re.sub(r"\w","", text, flags = re.I)
print(result)

خروجی:

, '@ '  ?   % $  .

خروجی نشان می دهد که تمام اعداد و حروف الفبا حذف شده اند.

حذف کاراکترهای غیر کلمه ای

برای حذف تمام کاراکترهای غیر کلمه، \W الگو را می توان به صورت زیر استفاده کرد:

text = "The film, '@Pulp Fiction' was ? released in % $ year 1994."
result = re.sub(r"\W", "", text, flags=re.I)
print(result)

خروجی:

ThefilmPulpFictionwasreleasedinyear1994

از خروجی می بینید که همه چیز حذف شده است (حتی فاصله ها) به جز اعداد و حروف الفبا.

گروه بندی الگوهای چندگانه

می توانید الگوهای متعددی را برای مطابقت یا جایگزینی در یک رشته با استفاده از براکت مربع گروه بندی کنید. در واقع ما این کار را زمانی انجام دادیم که حروف بزرگ و کوچک را با هم تطبیق دادیم. بیایید چندین علامت نگارشی را گروه بندی کنیم و آنها را از یک رشته حذف کنیم:

text = "The film, '@Pulp Fiction' was ? released _ in % $ year 1994."
result = re.sub(r"(,@\'?\.$%_)", "", text, flags=re.I)
print(result)

خروجی:

The film Pulp Fiction was  released  in   year 1994

می بینید که رشته در متغیر متن دارای چندین علامت نگارشی است، ما همه این علائم نگارشی را در عبارت regex با استفاده از براکت مربع گروه بندی کردیم. ذکر این نکته ضروری است که با یک نقطه و یک نقل قول باید از دنباله فرار یعنی اسلش به عقب استفاده کنیم. این به این دلیل است که به طور پیش فرض عملگر نقطه برای هر کاراکتری استفاده می شود و از تک نقل قول برای نشان دادن یک رشته استفاده می شود.

حذف فاصله های متعدد

گاهی اوقات در نتیجه حذف کلمات یا علائم نگارشی، فاصله های متعددی بین کلمات ظاهر می شود. به عنوان مثال، در خروجی آخرین مثال، فاصله های متعددی بین آنها وجود دارد in و year. این فضاها را می توان با استفاده از \s الگو، که به یک فضای واحد اشاره دارد.

text = "The film      Pulp Fiction      was released in   year 1994."
result = re.sub(r"\s+"," ", text, flags = re.I)
print(result)

خروجی:

The film Pulp Fiction was released in year 1994.

در اسکریپت بالا از عبارت استفاده کردیم \s+ که به فضاهای منفرد یا چندگانه اشاره دارد.

حذف Spaces از شروع و پایان

گاهی اوقات جمله ای داریم که با فاصله شروع یا به پایان می رسد که اغلب مطلوب نیست. اسکریپت زیر فاصله های ابتدای جمله را حذف می کند:

text = "         The film Pulp Fiction was released in year 1994"
result = re.sub(r"^\s+", "", text)
print(result)

خروجی:

The film Pulp Fiction was released in year 1994

به طور مشابه، برای حذف فضای انتهای رشته، می توان از اسکریپت زیر استفاده کرد:

text = "The film Pulp Fiction was released in year 1994      "
result = re.sub(r"\s+$", "", text)
print(result)

حذف یک کاراکتر

گاهی اوقات حذف علائم نگارشی، مانند آپستروف، منجر به یک کاراکتر می شود که معنایی ندارد. به عنوان مثال، اگر آپستروف را از کلمه حذف کنید Jacob's و آن را با فاصله جایگزین کنید، رشته حاصل است Jacob s. اینجا s معنی ندارد. چنین کاراکترهای منفرد را می توان با استفاده از regex همانطور که در زیر نشان داده شده است حذف کرد:

text = "The film Pulp Fiction     s was b released in year 1994"
result = re.sub(r"\s+(a-zA-Z)\s+", " ", text)
print(result)

خروجی:

The film Pulp Fiction was released in year 1994

اسکریپت هر حرف کوچک یا بزرگ بین یک یا چند فاصله را با یک فاصله جایگزین می‌کند.

تقسیم یک رشته

تقسیم رشته یکی دیگر از عملکردهای بسیار مهم است. رشته ها را می توان با استفاده از تقسیم کرد split عملکرد از بسته re. را split تابع لیستی از نشانه های تقسیم شده را برمی گرداند. بیایید یک رشته از کلمات را در جایی که یک یا چند کاراکتر فاصله پیدا می شود، تقسیم کنیم، همانطور که در زیر نشان داده شده است:

text = "The film      Pulp   Fiction was released in year 1994      "
result = re.split(r"\s+", text)
print(result)

خروجی:

('The', 'film', 'Pulp', 'Fiction', 'was', 'released', 'in', 'year', '1994', '')

به طور مشابه، می توانید از دیگر عبارات regex برای تقسیم یک رشته با استفاده از عبارت استفاده کنید split کارکرد. به عنوان مثال، موارد زیر split تابع وقتی یک کاما پیدا می شود رشته کلمات را تقسیم می کند:

text = "The film, Pulp Fiction, was released in year 1994"
result = re.split(r"\,", text)
print(result)

خروجی:

('The film', ' Pulp Fiction', ' was released in year 1994')

یافتن همه موارد

را match تابع یک مسابقه را انجام می دهد روی اولین عنصر در حالی که search تابع یک جستجوی جهانی انجام می دهد روی رشته و اولین نمونه مطابق را برمی گرداند.

به عنوان مثال، اگر رشته زیر را داشته باشیم:

text = "I want to buy a mobile between 200 and 400 euros"

ما می خواهیم تمام ارقام این رشته را جستجو کنیم. اگر از search تابع، فقط اولین رخداد ارقام یعنی 200 مطابق شکل زیر برگردانده می شود:

result = re.search(r"\d+", text)
print(result.group(0))

خروجی:

200

از سوی دیگر، findall تابع لیستی را برمی‌گرداند که شامل تمام عبارات منطبق مانند شکل زیر است:

text = "I want to buy a mobile between 200 and 400 euros"
result = re.findall(r"\d+", text)
print(result)

خروجی:

('200', '400')

شما می توانید از خروجی ببینید که هر دو “200” و “400” توسط findall تابع.

نتیجه

در این مقاله به بررسی برخی از متداول‌ترین توابع regex در پایتون پرداختیم. عبارات منظم برای پیش پردازش متن بسیار مفید هستند که می توانند بیشتر برای برنامه های مختلف استفاده شوند، مانند مدل سازی موضوع، طبقه بندی متن، تحلیل احساسات، و خلاصه سازی متن، و غیره.

(برچسب‌ها به ترجمه)# python



منتشر شده در 1403-01-27 13:52:07

امتیاز شما به این مطلب
دیدگاه شما در خصوص مطلب چیست ؟

آدرس ایمیل شما منتشر نخواهد شد.

لطفا دیدگاه خود را با احترام به دیدگاه های دیگران و با توجه به محتوای مطلب درج کنید