کار با عبارت های منظم در سوئیفت - بخش دوم

کار با عبارت های منظم در سوئیفت - بخش دوم

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

مثالی پیشرفته تر از کاربرد عبارت های منظم در سوئیفت

متد (:matchInString(_:options:range یکی از ساده ترین متدهاست که به (:enumerateMatchesInString(_:options:range:usingBlock که قابل انعطاف ترین و عمومی ترین متد در کلاس NSRegularExpression است متکی می باشد. این متد یک بلاک را پس از هر بار تطبیق فراخوانی می کند و شما را قادر به اجرای عملیات دلخواه خود می گرداند.

با ارسال یک یا بیشتر قانون تطبیق با استفاده از ثابت های NSMatchingOptions، شما می توانید از فراخوانی بلاک در سایر موقعیت ها نیز اطمینان حاصل نمایید. برای عملیات طولانی، می توانید تعیین کنید که بلاک به صورت دوره ای فراخوانی شده و یا عملیات در یک زمان مشخص پایان پذیرد. با استفاده از گزینه ReportCompletion می توانید تعیین کنید که بلاک باید پس از تکمیل فراخوانی شود.

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

در این سناریو در متن به دنبال رشته هایی شبیه به تاریخ هستیم و قصد داریم وجود یک تاریخ خاص در آنها را بررسی کنیم، برای این منظور تصور می کنیم که رشته های تاریخ دارای ساختار زیر هستند:

- سال که دارای دو یا چهار رقم است.

- تنها شامل قرن کنونی یعنی بین 2000 تا 2099، در نتیجه 1982 رد شده و 16 به معنای 2016 است.

- یک جداکننده پس از آن می آید.

- یک عدد بین 1 یا 12 که نشان دهنده ماه است پس از آن ظاهر می شود.

- یک جداکننده در ادامه می آید.

- یک عدد از 1 تا 31 که نشان دهنده روز است در ادامه ظاهر می شود.

عدد صفر قبل از ماه و تاریخ های یک رقمی می آید و جداکننده های معتبر شامل دش، نقطه و / هستند، لازم به ذکر است که تنها شرایط مذکور را در اعتبارسنجی تاریخ مد نظر قرار می دهیم، برای نمونه تاریخ هایی به صورت 2000-04-31 هم در حالی که آوریل تنها 30 روز دارد معتبر شناخته شده و یا در تاریخ 2009-02-29 سال 2009 کبیسه نیست بنابراین ماه فوریه تنها 28 روز دارد، اما اگرچه این تاریخ ها واقعی نیستند ولی در این مثال معتبر شناخته می شوند.

کد زیر را به playground اضافه کنید تا به صورت گام به گام به شرح آنچه در کد نوشته شده بپردازیم.

// (1):

typealias PossibleDate = (year: Int, month: Int, day: Int)

// (2):

func dateSearch(text: String, _ date: PossibleDate) -> Bool {

// (3):

let datePattern = "\\b(?:20)?(\\d\\d)[-./](0?[1-9]|1[0-2])[-./](3[0-1]|[1-2][0-9]|0?[1-9])\\b"

let dateRegex = try! NSRegularExpression(pattern: datePattern,

options: [])

// (4):

var wasFound: Bool = false

// (5):

dateRegex.enumerateMatchesInString(text, options: [],

range: NSRange(location: 0,

length: text.characters.count)) {

// (6):

(match, _, stop) in

var dateArr = [Int]()

for n in 1...3 {

let range = match!.rangeAtIndex(n)

let r = text.startIndex.advancedBy(range.location) ..<

text.startIndex.advancedBy(range.location+range.length)

dateArr.append(Int(text.substringWithRange(r))!)

}

// (7):

if dateArr[0] == date.year

&& dateArr[1] == date.month

&& dateArr[2] == date.day {

// (8):

wasFound = true

stop.memory = true

}

}

return wasFound

}

let text = " 2015/10/10,11-10-20, 13/2/2 1981-2-2 2010-13-10"

let date1 = PossibleDate(15, 10, 10)

let date2 = PossibleDate(13, 1, 1)

dateSearch(text, date1) // returns true

dateSearch(text, date2) // returns false

گام 1

تاریخ هایی که وجود آنها را چک می کنیم دارای یک فرمت استاندارد هستند و تنها یک عدد دورقمی را برای سال ارسال می کنیم و 16 به معنای 2016 می باشد.

گام 2

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

یک تابع برای انجام این کار می سازیم، این تابع در صورت پیدا شدن تاریخ true و در غیر این صورت false را برمی گرداند.

گام 3

الگوی تاریخ دارای ویژگی های جالبی است:

- به بخش ? ( ?:20 )  توجه کنید، چنانچه آن را با ? (20) جایگزین کنیم به ابن معنا خواهد بود که وجود 20 در سال که نمایش دهنده هزاره است  مشکلی ندارد. پرانتزها برای گروه بندی به کار می روند اما ساخت کپچر گروپ با استفاده از آنها هم امکان پذیر است و بیت ?: هم برای این کار مورد استفاده قرار می گیرد.

- جداکننده های محتمل در داخل مجموعه کاراکتر [/.-] نیازی به اسکیپ کردن برای اینکه معنای لفظی خود را بدهند ندارند. – در ابتدا قرار گرفته بنابراین نمی تواند نماینده یک محدوده باشد، کاراکتر . هم نمایش دهنده هیچ کاراکتری در داخل مجموعه کاراکتر نمی باشد.

- استفاده گسترده ای از نوار عمودی جهت نمایش احتمالات ماه و اعداد تاریخ شده است.

گام 4

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

گام 5

در این مرحله متد (:enumerateMatchesInString(_:options:range:usingBlock فراخوانی شده و هیچیک از گزینه ها را مورد استفاده قرار نداده و کل محدوده را برای جستجو می فرستیم.

گام 6

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

- تطبیق (یک NSTextCheckingResult).

- فلگ هایی که نشان دهنده وضعیت کنونی فرآیند تطبیق هستند.

- متغیر بولین stop که می توان آن را در بلاک ست کرد تا زودتر از بلاک خارج شود.

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

گام 7

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

گام 8

چنانچه یک تطبیق پیدا شود notFound را به مقدار true ست کرده و با ست کردن stop.memory به مقدار true از بلاک خارج می شویم. دلیل این کار این است که stop یک pointer-to-a-boolean است و سوئیفت از طریق ویژگی memory با حافظه pointed-to سر و کار دارد.

زیررشته 2015/10/10 در متن با (PossibleDate(15, 10, 10 مطابقت دارد، به همین دلیل تابع در حالت اول true برمی گرداند. هیچ رشته ای در متن با (PossibleDate(13, 1, 1 که همان تاریخ 01-01-2013 است مطابقت ندارد بنابراین فراخوانی تابع false را برمی گرداند.

blog_20296_1

جمع بندی

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

 

http://code.tutsplus.com برگرفته از

 

اینها را هم بخوانید