แปลงแท็กปิด PHP เป็นความคิดเห็น


149

หนึ่งในบรรทัดในสคริปต์ของฉันมีแท็กปิด PHP ภายในสตริง ภายใต้การทำงานปกติสิ่งนี้ไม่ได้ทำให้เกิดปัญหา แต่ฉันต้องใส่ความคิดเห็นออกไป

ผมได้พยายามที่จะแสดงความคิดเห็นออกบรรทัดนี้ด้วย//, /* */และ#แต่ไม่มีของการทำงานของพวกเขาแยกวิเคราะห์พิจารณาปิดแท็กจะเป็นแท็กปิดที่เกิดขึ้นจริง

นี่คือบรรทัดในคำถาม:

$string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i', '<br />', $string);
//                              ^^             ^^

ฉันจะทำอย่างไรเพื่อแสดงความคิดเห็นในบรรทัดด้านบน


18
ปัญหาตลก แต่จริง ฉันลงคะแนน
Voitcus

17
พระเจ้าช่วย. ตอนแรกฉันสงสัยคำถามของคุณพร้อมที่จะถามว่าปัญหาคืออะไร แต่จากนั้นฉันพยายามที่จะแสดงความคิดเห็นบรรทัดที่มีสตริงที่มี '?>' และฉันได้รับมัน สิ่งนี้ควรถูกเพิ่มเข้าไปในรายชื่อยาวของphpsadness.com
lolesque

6
ประโยชน์ของ "ฟีเจอร์" ดังกล่าวได้อธิบายไว้ในphp.net/manual/en/language.basic-syntax.comments.phpซึ่งมีประโยชน์ในกรณีที่มีซับใน<?php # echo 'simple';?>หนึ่งอัน
lolesque

2
@lolesque ขอบคุณสำหรับลิงค์ ที่ดีอย่างหนึ่ง ภาษาที่เกี่ยวข้องซึ่งครอบคลุมภาษาอื่นเช่นกัน: wiki.theory.org/YourLanguageSucks
Simon Forsberg

5
@ OndraŽižkaทั้งหมดที่เขาทำคือการลบแท็ก br ซ้ำ regex ทำงานได้ดีสำหรับการที่ เพียงเพราะบางครั้งมันไม่ดีไม่ได้หมายความว่ามันไม่ดีตลอดเวลา
คิป

คำตอบ:


124

ใช้เคล็ดลับ: เชื่อมสตริงจากสองชิ้น ด้วยวิธีนี้แท็กปิดจะถูกตัดเป็นสองส่วนและไม่ใช่แท็กปิดที่ถูกต้องอีกต่อไป'?>' --> '?'.'>'

ในรหัสของคุณ:

$string = preg_replace('#<br\s*/?'.'>(?:\s*<br\s*/?'.'>)+#i', '<br />', $string);

สิ่งนี้จะทำให้//ความคิดเห็นทำงานได้

สำหรับ/* */ความคิดเห็นในการทำงานคุณจะต้องแยก*/ลำดับดังนี้:

$string = preg_replace('#<br\s*'.'/?'.'>(?:\s*<br\s*'.'/?'.'>)+#i', '<br />', $string);

โปรดจำไว้ว่าบางครั้งแม้ว่าทั้งหมดจะมากขึ้นกว่าผลรวมของส่วนของตน - แต่โลภไม่ดีมีบางครั้งที่คุณจะเหลือดีกว่าที่มีน้อย :)


@ppeterka ว้าวฉันไม่ได้คิดอย่างนั้น ขอบคุณ.
v1n_vampire

1
ฉันต้องใช้เคล็ดลับนี้ใน C 2 วันก่อนสำหรับสตริงที่มี??<
Ryan Amos

2
เยี่ยมมาก ทำไมฉันไม่เคยคิดแบบนั้น!
San

73

วิธีที่ง่ายที่สุด

สร้างตัวแปรแยกต่างหากเพื่อเก็บนิพจน์ปกติของคุณ วิธีนี้คุณสามารถคอมเม้นท์preg_replace()ข้อความนี้ได้:

$re = '#<br\s*/?>(?:\s*<br\s*/?>)+#i';
// $string = preg_replace($re, '<br />', $string);

แก้ไขโดยใช้คลาสตัวละคร

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

$string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i', '<br />', $string);
                                 ^ ^              ^ ^

หากต้องการแก้ไขความคิดเห็นบล็อกคุณสามารถนำไปใช้กับ/:

$string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i', '<br />', $string);
                               ^ ^              ^ ^

หากต้องการแก้ไขทั้งสไตล์ความคิดเห็นคุณสามารถใส่/ และ >ในคลาสตัวละครของตนเอง

แก้ไขโดยใช้โมดิ/xฟายเออร์

โมดิx ฟายเออร์ - aka PCRE_EXTENDED- ละเว้นช่องว่างและบรรทัดใหม่ในนิพจน์ทั่วไป (ยกเว้นเมื่อเกิดขึ้นภายในคลาสอักขระ) ทำให้สามารถเพิ่มช่องว่างเพื่อแยกอักขระที่มีปัญหาได้ ในการแก้ไขสไตล์ความคิดเห็นทั้งสอง:

$string = preg_replace('#<br\s* /? >(?:\s*<br\s* /? >)+#ix', '<br />', $string);
                               ^  ^             ^  ^

@Cthulhu +1 (และสำหรับคำตอบด้วยแน่นอน) นอกจากนี้ (อย่างน้อยสำหรับฉัน) นี่ทำให้ regexp ค่อนข้างยากที่จะเข้าใจ ไม่มาก แต่ถ้าฉันเห็น regex นี้ฉันจะพูดว่า: อืมเกิดอะไรขึ้น แต่นั่นเป็นเรื่องจริงจังและเป็นอัตวิสัยโดยสิ้นเชิง
ppeterka

1
@ppeterka ผมค่อนข้างเห็นด้วยดังนั้นฉันได้พบวิธีอื่นโดยใช้การxปรับปรุง :)
แจ็ค

@ Jack ดีฉันจะให้ +1 อีกสำหรับฉันได้เรียนรู้สิ่งใหม่ ... ฉันลืมเกี่ยวกับการปรับเปลี่ยน regex (ฉันไม่ค่อยใช้พวกเขานอกเหนือจากg) ...
ppeterka

@ แจ็คขอบคุณฉันเรียนรู้สิ่งใหม่เกี่ยวกับ regex จากการแก้ปัญหา
v1n_vampire

1
+1 สำหรับแยก regex ออกเป็นบรรทัดก่อนหน้า มันทำให้ regex เหมือนเดิม แต่ก็ยังอนุญาตให้ใส่ความเห็นได้

38

ทำไมความพยายามของคุณไม่ทำงาน:

// $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',...
                                   ^ doesn't work due to ?> ending php

/* $string = preg_replace('#<br\s*/?>(?:\s*<br\s*/?>)+#i',... */
                                 ^ doesn't work due to */ closing comment

งานอะไร:

/* $string = preg_replace('#<br\s*[/]?>(?:\s*<br\s*[/]?>)+#i',... */
                                  ^ ^              ^ ^
// $string = preg_replace('#<br\s*/?[>](?:\s*<br\s*/?[>])+#i',...
                                    ^ ^              ^ ^

เพิ่มเติม ...

หลังจากข้างต้นคุณควรจะสามารถใช้/*เพื่อแสดงความคิดเห็นออกสาย หากคุณปล่อยให้?>ไม่บุบสลาย//ไม่สามารถแสดงความคิดเห็นทั้งบรรทัด ข้อความต่อไปนี้?>อาจเป็น html ซึ่งอยู่นอกเหนือการควบคุมของล่าม PHP ดังนั้นจึงไม่ทำงาน

จากเอกสาร:

สไตล์ความคิดเห็น "หนึ่งบรรทัด" แสดงความคิดเห็นเฉพาะที่ส่วนท้ายของบรรทัดหรือบล็อกปัจจุบันของโค้ด PHP แล้วแต่ว่าจะถึงอย่างใดก่อน ซึ่งหมายความว่าโค้ด HTML หลังจาก // ... ?> หรือ # ... ?> จะถูกพิมพ์:?> แบ่งออกจากโหมด PHP และกลับไปที่โหมด HTML และ // หรือ # ไม่สามารถมีอิทธิพลต่อสิ่งนั้นได้


ขอบคุณหลายสิ่งที่ฉันยังไม่รู้ ... มันมีประโยชน์
v1n_vampire

4
โพสต์นี้จะสมควรได้รับ +1 เพิ่มเติม ... สำหรับคำอธิบายอย่างละเอียดเพียงอย่างเดียว
ppeterka

15

แนวคิดอื่น: หลีกเลี่ยง>(และ/ถ้าคุณต้องการใช้/*...*/ความคิดเห็น):

$string = preg_replace('#<br\s*\/?\>(?:\s*<br\s*\/?\>)+#i', '<br />', $string);

การยกเว้น "ไม่จำเป็น" จะถูกละเว้นโดยเอ็นจิน regex แต่มีประโยชน์ในกรณีนี้ (ด้วยเหตุผลที่อธิบายไว้ในคำตอบอื่น ๆ )


@ppeterka: ฉันใช้แบ็กสแลชแทนคลาสอักขระ (แต่ใช่ฉันพลาดไปหนึ่งครั้งแล้วขอบคุณ!)
Tim Pietzcker

ขออภัยดูเหมือนว่าฉันเหนื่อย ... ฉันสังเกตเห็นคนที่สองที่ถูกทิ้งไว้ในนั้นล้อมรอบด้วย [] ...
ppeterka

10

เหตุใดจึงต้องใช้ "ลูกเล่น" ที่ซับซ้อนและยากต่อการอ่านเพื่อแก้ปัญหา

? เป็นเพียงทางลัดของตัวปรับปริมาณเพื่อความสะดวกเท่านั้น

เพียงใช้ตัวระบุปริมาณแบบยาว{0,1}หมายความว่า "เกิดขึ้นอย่างน้อย 0 สูงสุด 1 สูงสุด":

$string = preg_replace('#<br\s*/{0,1}>(?:\s*<br\s*/{0,1}>)+#i', '<br />', $string);

1
+1 หน้านี้เริ่มเป็นสถานที่ที่ดีมากในการรวบรวมกลเม็ด regex ไว้ในใจของเรา
ppeterka

1
@ppeterka ฉันจะเรียกคำตอบอื่น ๆ ทั้งหมดว่า "กลอุบาย" แต่คำตอบของฉันคือการใช้ควอไลเซอร์รุ่นยาวไม่ใช่ทางลัด
stema

3
ไม่มีความผิดเพียงแค่นั้นในพจนานุกรมของฉันโดยใช้เวอร์ชันที่ยาวกว่าของนิพจน์แทนที่จะเป็นน้ำตาล
ซินแทกติก

8

วิธีอื่น ๆ ที่ควรเพิ่มในหนังสือเคล็ดลับ RegEx :

ก่อนอื่นคุณสามารถบีบอัด RegEx ของคุณไปที่: /(<br\s*/?>)+/iและแทนที่ด้วย<br />(ไม่ต้องเป็นภาระ RegExP ด้วย lookaheads) และคุณจะต้องจบลงด้วยตัวแบ่งบรรทัด XHMTL ที่คุณเลือก

วิธีอื่น ๆ ในการปรับเปลี่ยน RegEx ของคุณดังนั้นมันจะไม่*/แสดงความคิดเห็น?>สิ้นสุดหรือสคริปต์สิ้นสุด:

  • ใช้ปริมาณที่เป็นเจ้าของ : #(<br\s*+/?+>)+#i- ซึ่งโดยทั่วไปมีความหมายสำหรับ\s*+ถ้าคุณพบว่าช่องว่างตรงกับมากที่สุดเท่าที่มีและเก็บไว้และสำหรับ/?+ถ้าคุณพบเฉือนเก็บไว้!
  • ใส่\s*และ/*ในกลุ่มการจับ =>#(<br(\s*)(/?)>)+#i

การสาธิตสด: http://codepad.viper-7.com/YjqUbi

และเนื่องจากเราโน้มตัวไปทางพฤติกรรมที่เป็นเจ้าของ RegEx ที่เร็วที่สุดที่ยังเลี่ยงปัญหาการแสดงความคิดเห็นก็คือ: อธิบายการสาธิต#(<br\s*+/?+>)++#i


สำหรับการแสดงความคิดเห็นในสถานการณ์ที่ยุ่งยาก

เมื่อคุณไม่สามารถเปลี่ยนรหัสหรือใช้ความคิดเห็นหลายบรรทัดและ:

1. ใช้nowdoc :

    $string='Hello<br>World<br><br />World<br><br><br>Word!';
    <<<'comment'
    $string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
comment;

รหัสสด: http://codepad.viper-7.com/22uOtV

หมายเหตุ: nowdocนั้นคล้ายกับheredocแต่ไม่แยกวิเคราะห์เนื้อหาและจะต้องมีตัวคั่นเริ่มต้นล้อมรอบด้วย'เครื่องหมายคำพูดเดี่ยว'( โปรดทราบว่าตัวคั่นสิ้นสุดไม่สามารถระบุได้ต้องตามด้วย;และบรรทัดใหม่ ! )

2. กระโดดข้ามรหัสด้วยการข้ามไป :

$string='Hello<br>World<br><br />World<br><br><br>Word!';
goto landing;
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
landing:

ตัวอย่างสด: http://codepad.viper-7.com/UfqrIQ

3. ข้ามรหัสด้วยif(false)หรือif(0):

$string='Hello<br>World<br><br />World<br><br><br>Word!';
if(0){
$string = preg_replace('#(<br\s*/?>)+#i', '<br />', $string);
}

ทดสอบ: http://codepad.viper-7.com/wDg5H5

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