การจำกัดความละโมบในนิพจน์ปกติของ PHP

โดยค่าเริ่มต้น นิพจน์ปกติจะมี ความละโมบ ซึ่งหมายความว่าพวกมันจะจับตัวอักษรจำนวนมากที่สุดเท่าที่เป็นไปได้

ลองมาดูตัวอย่างกัน สมมติว่าเรามีสตริงดังนี้:

php<?php
  $str = 'aeeex zzz x kkk';
?>

สมมติว่าในสตริงนี้เราต้องการค้นหาสตริงย่อย 'aeeex' โดยใช้รูปแบบดังนี้: ตัวอักษร 'a' ตามด้วยอักขระใดๆ หนึ่งตัวหรือมากกว่า จากนั้นตามด้วยตัวอักษร 'x'

php<?php
  $res = preg_replace('#a.+x#', '!', $str);
?>

เราคาดหวังว่าในตัวแปร $res จะเก็บสตริง '! zzz x kkk' อย่างไรก็ตาม ไม่เป็นเช่นนั้น - ตัวแปรกลับเก็บสตริง '! kkk'

สาเหตุทั้งหมดอยู่ที่ว่านิพจน์ปกติของเราค้นหาทุก ตัวอักษรจากตัวอักษร 'a' ไปจนถึงตัวอักษร 'x' แต่ในสตริงของเรามีตัวอักษร 'x' อยู่สองตัว เนื่องจาก ความละโมบจึงทำให้นิพจน์ปกติค้นหาไปจนถึง ตัว 'x' สุดท้าย ทำให้จับส่วนที่เราไม่ได้คาดหวังไว้

แน่นอนว่าในหลายกรณีพฤติกรรมนี้เป็นสิ่งที่เราต้องการ แต่ในกรณีนี้โดยเฉพาะ เราอยากยกเลิกความละโมบ และบอกนิพจน์ปกติให้ค้นหาไปจนถึงตัว 'x' ตัวแรก

เพื่อจำกัดความละโมบ จำเป็นต้องใส่เครื่องหมายคำถาม หลังโอเปอเรเตอร์การทำซ้ำ:

php<?php
  $res = preg_replace('#a.+?x#', '!', $str);
?>

สามารถจำกัดความละโมบให้กับโอเปอเรเตอร์การทำซ้ำทั้งหมดได้ ดังนี้: *?, ?? และ {}?

Задание 1

กำหนดสตริง:

php<?php
  $str = 'aba accca azzza wwwwa';
?>

เขียนนิพจน์ปกติที่ค้นหาสตริงทั้งหมด ซึ่งมีตัวอักษร 'a' อยู่ที่ขอบทั้งสองด้าน และแทนที่แต่ละสตริงด้วย '!' ระหว่าง ตัวอักษร a สามารถเป็นอักขระใดๆ ก็ได้ (ยกเว้น ตัวอักษร 'a')