ฉันจะแปลงนิพจน์ ereg เป็น preg ใน PHP ได้อย่างไร


140

ตั้งแต่นิพจน์ปกติ POSIX (ereg)จะเลิกตั้งแต่ PHP 5.3.0 ผมอยากที่จะรู้ว่าเป็นวิธีที่ง่ายในการแปลงสำนวนเก่าที่จะPCRE (นิพจน์ปกติ Perl เข้ากันได้) (อายุครรภ์)

ตัวอย่างเช่นฉันมีนิพจน์ทั่วไปนี้:

eregi('^hello world');

ฉันจะแปลนิพจน์เป็นpreg_matchนิพจน์ที่ใช้ร่วมกันได้อย่างไร

หมายเหตุ:โพสต์นี้ทำหน้าที่เป็นตัวยึดตำแหน่งสำหรับโพสต์ทั้งหมดที่เกี่ยวข้องกับการแปลงจาก ereg เป็น preg และเป็นตัวเลือกที่ซ้ำกันสำหรับคำถามที่เกี่ยวข้อง โปรดอย่าปิดคำถามนี้

ที่เกี่ยวข้อง:


2
@ yes123: ใช่นั่นคือประเด็นฉันก็เบื่อเช่นกัน ฉันต้องการโพสต์วิกิที่อธิบายบางสิ่งบางอย่างจริง ๆ เพื่อให้เราสามารถปิดคำถามแต่ละข้อเหล่านี้ได้
netcoder

ฉันคิดว่าไม่จำเป็นสำหรับสิ่งนี้เพราะคุณเพียงแค่ต้องห่อเก่าด้วยตัวคั่น นอกจากนี้ฉันคิดว่าคุณอาจใช้คำถามที่ได้รับคำตอบก่อนหน้านี้สำหรับเรื่องนี้
ไดนามิก

อ่าโหวตให้ปิดก่อนที่จะอ่านความคิดเห็น ในฐานะที่เป็นตัวยึดตำแหน่งมันสามารถตอบสนองวัตถุประสงค์ แต่ไม่มีคำถามเก่าอีกคำถามที่สามารถใช้เป็นเช่นนี้ได้หรือไม่
Wrikken

อืมแน่นอน ereg [php]ไม่ให้ผลลัพธ์ที่มีประโยชน์มากนัก ตกลงสามารถให้การสนับสนุนฉันกับคนนี้
Wrikken

8
ดูเหมือนว่าเราเกือบจะได้สร้างคำถามปิดในหัวข้อนี้ทั้งหมดแล้วชี้ไปที่กันและกัน อัตรานี้พวกเขาทั้งหมดจะถูกปิด :)
Kev

คำตอบ:


142

การเปลี่ยนแปลงที่ใหญ่ที่สุดในไวยากรณ์คือนอกเหนือจากตัวคั่น

ereg('^hello', $str);
preg_match('/^hello/', $str);

ตัวคั่นอาจเป็นอะไรก็ได้ที่ไม่ใช่ตัวอักษรตัวเลขแบ็กสแลชหรืออักขระช่องว่าง ที่ใช้มากที่สุดคือโดยทั่วไป~, และ/#

คุณยังสามารถใช้วงเล็บที่ตรงกันได้:

preg_match('[^hello]', $str);
preg_match('(^hello)', $str);
preg_match('{^hello}', $str);
// etc

หากพบตัวคั่นของคุณในนิพจน์ทั่วไปคุณต้องหลบหนี:

ereg('^/hello', $str);
preg_match('/^\/hello/', $str);

คุณสามารถหลีกเลี่ยงตัวคั่นและอักขระสงวนทั้งหมดในสตริงได้อย่างง่ายดายโดยใช้preg_quote :

$expr = preg_quote('/hello', '/');
preg_match('/^'.$expr.'/', $str);

นอกจากนี้ PCRE ยังรองรับการดัดแปลงสำหรับสิ่งต่าง ๆ หนึ่งในที่สุดที่ใช้เป็นตัวปรับแต่งกรณีตายiทางเลือกที่จะeregi :

eregi('^hello', 'HELLO');
preg_match('/^hello/i', 'HELLO');

คุณสามารถค้นหาการอ้างอิงที่สมบูรณ์เกี่ยวกับไวยากรณ์ PCRE ใน PHP ในคู่มือรวมถึงรายการความแตกต่างระหว่าง POSIX regex และ PCRE เพื่อช่วยในการแปลงนิพจน์

อย่างไรก็ตามในตัวอย่างง่ายๆของคุณคุณจะไม่ใช้นิพจน์ทั่วไป:

stripos($str, 'hello world') === 0

2
คำอธิบายที่ยอดเยี่ยม! ฉันต้องการเพิ่มกรณีพิเศษที่คุณแปลงจากeregเป็นpreg_matchและคุณต้องหลบหนีเฉพาะตัวคั่นและไม่ใช่ตัวละครที่สงวนไว้ (เพราะพวกเขาทำงานเป็นตัวละครพิเศษแล้วเราไม่ต้องการหนีพวกเขา) : preg_match ('/'. str_replace ('/', '\ /', $ expr). '/', $ str);
Lolito

เป็นเรื่องที่น่าสังเกตว่าถ้าคุณใช้วงเล็บที่ตรงกันคุณไม่จำเป็นต้องหลบเลี่ยงตัวละครใด ๆ "เพียงเพราะมันเหมือนกับตัวคั่น" เหมือนกับที่คุณทำกับสัญลักษณ์อื่น ๆ เช่น/^\/hello/ตัวอย่าง (a(b)c)เป็น PCRE ที่ถูกต้องสมบูรณ์และมีตัวคั่น โดยส่วนตัวฉันชอบใช้วงเล็บ()เพื่อเตือนตัวเองว่าการจับคู่ครั้งแรกนั้นเป็นสิ่งที่เกิดขึ้นทั้งหมด
Niet the Dark Absolute

ฉันสามารถพูดได้ไหมฉันเกลียดชัง PHP! (.. เพียงว่าไม่มีอะไรอื่น) ฉันต้องค้นหาคำตอบเหล่านี้ออกมาเมื่อเว็บโฮสติ้งเซิร์ฟเวอร์ที่ใช้ร่วมกันของฉันได้รับการปรับปรุงเป็นรุ่นใหม่และerror_logs PHP Deprecated: Function ereg() is deprecated in...ได้รับเต็มไปด้วยคำเตือนเหล่านี้: โอ๊ะ!
c00000fd

วิธีการแปลงนี้ $ regex = $ e '((\. [^ \.'. $ e. '] [^'. $ e. '] *) | (\. \. [^'. $ e. '] +) | ([^ \ ] [^ '. $ e.'] *)) ' $ e '\. \. . $ E; เพื่อ preg_math มันทำงานได้โดยเพียงแค่เพิ่ม / แก้ไข /
bdalina

32

การแทนที่ Ereg ด้วย preg (ตั้งแต่ PHP 5.3.0) เป็นการเปลี่ยนแปลงที่ถูกต้องในความโปรดปรานของเรา

preg_match ซึ่งใช้ไวยากรณ์นิพจน์ปกติที่เข้ากันได้กับ Perl มักจะเป็นทางเลือกที่เร็วกว่าสำหรับ ereg

คุณควรรู้ 4 สิ่งสำคัญในการพอร์ตรูปแบบ ereg เพื่อ preg:

  1. เพิ่มตัวคั่น (/):'pattern' => '/pattern/'

  2. หลีกเลี่ยงตัวคั่นหากเป็นส่วนหนึ่งของรูปแบบ: 'patt/ern' => '/patt\/ern/'
    บรรลุโดยทางโปรแกรมในวิธีต่อไปนี้:
    $old_pattern = '<div>.+</div>';
    $new_pattern = '/' . addcslashes($old_pattern, '/') . '/';

  3. eregi (การจับคู่ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่): 'pattern' => '/pattern/i' ดังนั้นหากคุณใช้ฟังก์ชัน eregi สำหรับการจับคู่แบบตัวพิมพ์เล็กและใหญ่ให้เพิ่ม 'i' ในส่วนท้ายของรูปแบบใหม่ ('/ pattern /')

  4. ค่า ASCII : ใน ereg หากคุณใช้ตัวเลขในรูปแบบจะถือว่าคุณกำลังอ้างถึง ASCII ของอักขระ แต่ใน preg หมายเลขจะไม่ถือว่าเป็นค่า ASCII ดังนั้นหากรูปแบบของคุณมีค่า ASCII ในนิพจน์ ereg (ตัวอย่างเช่น: บรรทัดใหม่, แท็บ ฯลฯ ) จากนั้นแปลงเป็นรูปแบบเลขฐานสิบหกและนำหน้าด้วย \ x
    Example: 9(tab) becomes \x9 or alternatively use \t.


8

จาก PHP เวอร์ชั่น 5.3 eregเลิกใช้แล้ว

การย้ายจากeregไปpreg_matchเป็นเพียงการเปลี่ยนแปลงเล็กน้อยในรูปแบบของเรา

ก่อนอื่นคุณต้องเพิ่มตัวคั่นลงในรหัสของคุณเช่น:

ereg('A-Z0-9a-z', 'string');

ถึง

preg_match('/A-Z0-9a-z/', 'string');

สำหรับeregiการจับคู่ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่ให้ใส่iหลังตัวคั่นล่าสุดเช่น:

eregi('pattern', 'string');

ถึง

preg_match ('/pattern/i', 'string');

7

มีความแตกต่างระหว่างereg()และpreg_replace()มากกว่าแค่ไวยากรณ์:

  • ค่าส่งคืน:

    • ข้อผิดพลาด : คืนค่าทั้งคู่FALSE
    • โดยไม่มีการแข่งขัน : ereg()return FALSE, preg_match()return0
    • ในการแข่งขัน : ereg()ส่งกลับความยาวสตริงหรือ1, preg_match()ผลตอบแทนเสมอ1
  • อาร์เรย์ผลลัพธ์ของสตริงย่อยที่ตรงกัน: หากไม่พบสตริงย่อยบางรายการ ( (b)ใน...a(b)?) รายการที่สอดคล้องกันในereg()ผลลัพธ์จะเป็นFALSEในขณะpreg_match()นั้นจะไม่มีการตั้งค่าเลย

หากไม่มีความกล้าพอที่จะแปลงเขาหรือเธอereg()เป็นpreg_match()เขาหรือเธออาจใช้mb_ereg ()ซึ่งยังคงมีอยู่ใน PHP 7

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.