پاسخ به روز شده
ساختار های lookaround توسط اکثر موتور های عبارات با قاعده پشتیبانی نمیشوند و در آن هایی که پشتیبانی می شوند هم نوع استفاده ی یکسانی ندارند. مثلا در NET. می توان از lookbehind ای با طول متغیر (variable-length lookbehind) استفاده کرد (مثل استفاده از شمارنده هایی چون ستاره *
) اما در PCRE این فیچر وجود ندارد. برای به دست آوردن نتیجه ی دلخواه، شما دو راه دارید:
استفاده از lookbehind (همانطور که دنبالش بودید):
ریجکس:
(?<!a |a)test
کد PHP:
echo preg_replace('~(?<!a |a)test~', '***', 'this is a test test text');
// this is a test *** text
از آنجایی که محدودیت ذکر شده در PCRE وجود دارد نمی توان از (?<!a *)test
استفاده کرد. اما ما می توانیم در PCRE از alternation استفاده کنیم و طرفین پایپ |
را با یک طول ثابت نمایش دهیم. برای همین من در یک سمت آلترنیشن از کاراکتر a
ای که به همراه فاصله می آید استفاده کردم و در طرف دیگر یک کاراکتر a
قرار داده ام.
استفاده از فعل بک ترک SKIP
:
ریجکس:
a *test(*SKIP)(*F)|test
کد PHP:
echo preg_replace('~a *test(*SKIP)(*F)|test~', '***', 'this is a test test text');
// this is a test *** text
فعل بک ترک SKIP
در واقع به عنوان حذف کننده ی هر آنچه تا کنون پیمایش شده به کار می رود. هر چه قبل از این توکن بیاید match می شود ولی سریعا موتور از روی آن میپرد. این پریدن زمانی صورت می گیرد که ریجکسی در ادامه ی این فعل بیاید که منجر به "بک ترک" در پیمایش بشود. برای همین این فعل کنار فعل F
یا همان FAIL
می آید. FAIL
موتور را مجبور میکند تا به مسیر های قبلی برگردد و انتخاب دیگری بکند. موتور به عقب می رود و فعل SKIP
را می بیند. SKIP
سیگنالی میفرستد که "مسیر فعلی را قبول کن ولی آن را در حافظه خروجی ذخیره نکن". موتور سیگنال را میگیرد و به ادامه ی پیمایش می پردازد.
من در طرف چپ آلترنیشن تمامی test
هایی که بعد از a
یا a
با فاصله آمده اند را match می کنم و از طریق افعال استفاده شده به موتور می فهمانم که این رشته ها را در خروجی نمی خواهم. در عوض آنچه در سمت راست آلترنیشن می آید را برایم match کن.