مسیرها
/
Factor
Factor
/
تمرین‌ها
/
دیده‌بان دفتر
دیده‌بان دفتر

دیده‌بان دفتر

تمرین یادگیری

مقدمه

شما اصول اولیه را از قبل می‌دانید: کلاس‌های کاراکتر مانند \d و [A-Z]، کمیت‌سازهایی مانند {4} و +، و واژه‌های matches?، all-matching-subseqs و re-replace. این تمرین بخش‌هایی از عبارات باقاعده را اضافه می‌کند که ساختار و بافت را توصیف می‌کنند. این بخش‌ها در همان واژگان regexp قرار دارند و با همان نوشتار R/ / نوشته می‌شوند.

لنگرها

«لنگرها» به‌جای یک کاراکتر، یک موقعیت را تطبیق می‌دهند:

^    ! the start of the string
$    ! the end of the string
\b   ! a word boundary

چون $ به معنای پایان رشته است، وقتی منظورتان علامت دلار واقعی است \$ بنویسید.

یک «مرز واژه» (\b) نقطه‌ای است که یک «کاراکتر واژه» به یک کاراکتر غیرواژه می‌رسد. کاراکترهای واژه حروف، رقم‌ها و زیرخط هستند؛ هر چیز دیگری (فاصله‌ها، نشانه‌گذاری و دو سر رشته) مرز به حساب می‌آید. پس \bcat\b تنها وقتی cat را تطبیق می‌دهد که واژه به‌تنهایی بایستد:

USING: regexp ;

"cat nap" R/ \bcat\b/ re-contains? .   ! => t
"scatter" R/ \bcat\b/ re-contains? .   ! => f   (cat sits inside a word)

گروه‌بندی و جانشینی

پرانتزها ( ) بخشی از یک الگو را گروه‌بندی می‌کنند تا یک کمیت‌ساز، یا یک | («این یا آن»)، به کل گروه اعمال شود:

USING: regexp ;

"abab" R/ (ab)+/ matches? .                ! => t   (+ applies to "ab")
"dog"  R/ cat|dog/ matches? .              ! => t   (either word)
"$100.50" R/ \$\d+(\.\d{2})?/ matches? .   ! => t
"$100"    R/ \$\d+(\.\d{2})?/ matches? .   ! => t   (the group is optional)

الگوی آخر این‌طور خوانده می‌شود: «یک علامت دلار، یک یا چند رقم، و سپس یک گروه اختیاری از یک نقطه و دو رقم».

توجه: در Factor، یک گروه فقط الگو را ساختاردهی می‌کند. برخلاف برخی ابزارهای عبارات باقاعده، نمی‌توانید متنی را که یک گروه تطبیق داده است بیرون بکشید؛ استخراج گروه ثبت وجود ندارد و بازارجاع‌هایی مانند \1 پشتیبانی نمی‌شوند. برای بیرون کشیدن متن پیرامون یک نشانه، به‌جای آن از جست‌وجوی پیرامونی استفاده کنید (در ادامه).

جست‌وجوی پیرامونی: تطبیق بر پایه‌ی بافت، بدون مصرف کردن آن

جست‌وجوی پیرامونی بررسی می‌کند چه چیزی درست پیش یا درست پس از موقعیت جاری می‌آید، بدون آنکه این کاراکترها بخشی از تطبیق شوند. این جست‌وجو «عرض صفر» است: آنچه می‌آزماید در نتیجه گنجانده نمی‌شود.

(?=...)    ! lookahead:           ... must follow
(?!...)    ! negative lookahead:  ... must NOT follow
(?<=...)   ! lookbehind:          ... must come before
(?<!...)   ! negative lookbehind: ... must NOT come before

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

USING: regexp ;

"3 for $10 or 10 for $30" R/ \d+/ all-matching-subseqs .
! => { "3" "10" "10" "30" }   (every number)

"3 for $10 or 10 for $30" R/ (?<=\$)\d+/ all-matching-subseqs .
! => { "10" "30" }            (only the prices — the bare 3 and 10 drop)

"buy 2 at 15% off, 4 at 30% off" R/ \d+(?=%)/ all-matching-subseqs .
! => { "15" "30" }            (only the discounts — the bare 2 and 4 drop)

گزینه‌ها

برای تغییر رفتار کل الگو، یک حرف پس از / پایانی اضافه کنید. i آن را بی‌اعتنا به بزرگی و کوچکی حروف می‌کند:

USING: regexp ;

"REFUND"  R/ refund/i matches? .       ! => t
"Refund"  R/ refund/i matches? .       ! => t

تبدیل هر تطبیق

all-matching-subseqs متن تطبیق‌خورده را به شما می‌دهد. map-matches یک قدم فراتر می‌رود: یک quotation را روی هر تطبیق اجرا می‌کند و نتیجه‌ها را جمع می‌کند. این quotation اندیس start تطبیق، اندیس end آن و کل رشته را دریافت می‌کند؛ سپس subseq این سه را به متن تطبیق‌خورده تبدیل می‌کند و شما آن را تبدیل می‌کنید:

map-matches ( string regexp quot: ( start end string -- obj ) -- seq )
USING: math regexp sequences ;

"a1 b22 c333" R/ \d+/ [ subseq length ] map-matches .
! => { 1 2 3 }     (the length of each run of digits)

همتای عوارض‌محور آن، each-match، یک quotation را روی هر تطبیق اجرا می‌کند بدون اینکه چیزی جمع کند.

دستورالعمل‌ها

شما دفاتر حساب‌های یک شرکت کوچک را نگه می‌دارید و تراکنش‌های هر روز به شکل خطوط نامرتبی از متن می‌رسند. از «عبارات باقاعده» استفاده می‌کنید تا مبلغ‌ها را اعتبارسنجی کنید، اعداد را با نمادی که مشخصشان می‌کند استخراج کنید و خطوطی را که به بررسی دقیق‌تری نیاز دارند علامت بزنید.

1. اعتبارسنجی یک مبلغ

یک مبلغ خوش‌ساختار از یک $، یک یا چند رقم، و یک بخش سِنت اختیاری تشکیل شده که یک نقطه و دقیقاً دو رقم است: $100 یا $100.50، اما نه $100.5. تابع valid-amount? را تعریف کنید که وقتی کل رشته یک مبلغ خوش‌ساختار باشد t را برمی‌گرداند.

"$100.50" valid-amount? .   ! => t
"$100"    valid-amount? .   ! => t
"$100.5"  valid-amount? .   ! => f

2. اعداد دلاری را استخراج کنید

تابع dollar-amounts را تعریف کنید که هر عددی را که مستقیماً پس از یک $ در خط می‌آید، به ترتیب، برمی‌گرداند: فقط ارقام را، بدون $.

"spent $100 and $25 today" dollar-amounts .
! => { "100" "25" }

3. درصدها را استخراج کنید

تابع percentages را تعریف کنید که هر عددی را که بلافاصله بعد از یک % می‌آید برمی‌گرداند.

"up 5% then down 12%" percentages .
! => { "5" "12" }

4. یک خط را علامت بزنید

تابع flagged? را تعریف کنید که وقتی خط در هر ترکیبی از حروف بزرگ و کوچک به refund یا chargeback اشاره کند، t را برمی‌گرداند.

"Issued a REFUND today" flagged? .   ! => t
"a normal sale"         flagged? .   ! => f
ویرایش از طریق GitHub این لینک در پنجره یا زبانه‌ی جدیدی باز می‌شود
Factor Exercism

آماده‌اید دیده‌بان دفتر را شروع کنید؟

در Exercism ثبت‌نام کنید تا Factor را همراه با 47 مفهوم163 تمرین و مربی‌گری انسانی واقعی یاد بگیرید و در آن استاد شوید، همه‌ی این‌ها رایگان.