Chuyển đổi thẻ đóng PHP thành bình luận


149

Một trong những dòng trong tập lệnh của tôi chứa thẻ đóng PHP bên trong một chuỗi. Trong hoạt động bình thường, điều này không gây ra vấn đề, nhưng tôi cần bình luận.

Tôi đã cố gắng nhận xét ra dòng này với //, /* */#nhưng ai trong số họ làm việc, phân tích cú pháp xem xét thẻ đóng là một thẻ đóng thực tế.

Đây là dòng trong câu hỏi:

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

Tôi có thể làm gì để bình luận về dòng trên?


18
Vấn đề buồn cười, nhưng có thật. Tôi bỏ phiếu lên.
Voitcus

17
CHÚA ƠI. Lúc đầu, tôi đã nghi ngờ câu hỏi của bạn, sẵn sàng hỏi vấn đề là gì, nhưng sau đó tôi đã cố gắng bình luận một dòng có một chuỗi chứa '?>' Và tôi đã hiểu. Điều này nên được thêm vào danh sách dài của phpsadness.com
lolesque

6
Tính hữu dụng của một "tính năng" như vậy được giải thích trong php.net/manual/en/lingu.basic-syntax.comments.php , nó hữu ích trong trường hợp một lớp lót <?php # echo 'simple';?>.
lolesque

2
@lolesque Cảm ơn liên kết đó. Một trong những tốt. Một ngôn ngữ liên quan cũng bao gồm các ngôn ngữ khác: wiki.theory.org/YourL LanguageSucks
Simon Forsberg

5
@ OndraŽižka tất cả những gì anh ta đang làm là loại bỏ các thẻ br lặp đi lặp lại. một regex hoạt động tốt cho điều đó. Chỉ vì điều đó đôi khi không tốt có nghĩa là nó luôn tệ.
Kip

Câu trả lời:


124

Sử dụng một mẹo: nối chuỗi từ hai mảnh. Bằng cách này, thẻ đóng được cắt làm hai và không còn là thẻ đóng hợp lệ nữa.'?>' --> '?'.'>'

Trong mã của bạn:

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

Điều này sẽ làm cho //ý kiến ​​làm việc.

Để /* */bình luận hoạt động, bạn cũng phải chia */chuỗi:

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

Hãy nhớ rằng, đôi khi, mặc dù toàn bộ nhiều hơn tổng số các phần của nó - nhưng tham lam là xấu, có những lúc bạn tốt hơn nên bỏ đi với ít hơn . :)


@ppeterka Wow, tôi thậm chí không nghĩ về điều đó. Cảm ơn bạn.
v1n_v Vampire

1
Tôi đã phải sử dụng thủ thuật này trong C 2 ngày trước cho một chuỗi chứa??<
Ryan Amos

2
Tuyệt vời Tại sao tôi không bao giờ nghĩ như vậy!?
San

73

Cách dễ nhất

Tạo một biến riêng để giữ biểu thức chính quy của bạn; bằng cách này bạn chỉ cần bình luận ra preg_replace()tuyên bố:

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

Sửa lỗi sử dụng các lớp ký tự

Để sửa bình luận dòng, bạn có thể chia tay ?>bằng cách đặt >bên trong một lớp nhân vật như vậy:

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

Để sửa bình luận khối, bạn có thể áp dụng nó cho /:

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

Để sửa cả hai kiểu nhận xét, bạn có thể đặt / > trong lớp nhân vật của riêng họ.

Sửa lỗi bằng cách sử dụng công cụ /xsửa đổi

Công cụ x sửa đổi - aka PCRE_EXTENDED- bỏ qua khoảng trắng và dòng mới trong biểu thức chính quy (trừ khi chúng xuất hiện bên trong một lớp ký tự); điều này làm cho nó có thể thêm khoảng trắng để phân tách các ký tự có vấn đề. Để sửa cả hai kiểu nhận xét:

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

@Cthulhu +1 (và tất nhiên là cho câu trả lời). Ngoài ra (ít nhất là đối với tôi) điều này làm cho regrec khó hiểu hơn một chút. Không nhiều lắm, nhưng nếu tôi thấy regex này, tôi sẽ nói: Hmmm, chuyện gì đang xảy ra vậy? Nhưng đó là hết sức và hoàn toàn chủ quan.
ppeterka

1
@ppeterka Tôi phần nào đồng ý, vì vậy tôi đã tìm thấy một cách khác, bằng cách sử dụng công cụ xsửa đổi :)
Ja͢ck

@Jack Nice, tôi sẽ cho +1 khác cho nó, tôi đã học được một điều mới ... Tôi tiếp tục quên đi các công cụ sửa đổi regex (tôi hiếm khi sử dụng chúng ngoài g) ...
ppeterka

@Jack Cảm ơn bạn, tôi học được những điều mới về regex từ giải pháp.
v1n_v Vampire

1
+1 để tách regex ra trên một dòng trước đó. Nó giữ regex như cũ, nhưng vẫn cho phép logic được nhận xét.

38

Tại sao những nỗ lực của bạn không hoạt động:

// $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

Những gì hoạt động:

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

Thêm nữa...

Sau những điều trên, bạn sẽ có thể sử dụng /*để bình luận ra dòng. Nếu bạn để ?>nguyên vẹn, //không thể bình luận toàn bộ một dòng. Văn bản sau đây ?>có thể là html, nằm ngoài sự kiểm soát của trình thông dịch PHP, do đó sẽ không hoạt động.

Từ tài liệu:

Các kiểu nhận xét "một dòng" chỉ nhận xét đến cuối dòng hoặc khối mã PHP hiện tại, tùy theo cái nào đến trước. Điều này có nghĩa là mã HTML sau // ...?> Hoặc # ...?> SILL được in:?> Thoát khỏi chế độ PHP và trở về chế độ HTML và // hoặc # không thể ảnh hưởng đến điều đó.


Cảm ơn bạn, rất nhiều điều tôi vẫn không biết ... Thật hữu ích.
v1n_v Vampire

4
Bài đăng này sẽ xứng đáng hơn 1 giây ... Chỉ để giải thích cặn kẽ.
ppeterka

15

Một ý tưởng khác: Thoát khỏi >(và /, nếu bạn muốn sử dụng một /*...*/nhận xét):

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

Một lối thoát "không cần thiết" bị bỏ qua bởi công cụ regex, nhưng rất hữu ích trong trường hợp này (vì những lý do được nêu trong các câu trả lời khác).


@ppeterka: Tôi đã sử dụng dấu gạch chéo ngược thay vì lớp nhân vật (nhưng vâng, tôi đã bỏ lỡ một lần xuất hiện. Cảm ơn!)
Tim Pietzcker

Xin lỗi, có vẻ như tôi mệt mỏi ... Tôi nhận thấy cái thứ hai, bị bỏ lại ở đó bao quanh với [] ...
ppeterka

10

Tại sao sử dụng các "thủ thuật" phức tạp, khó đọc để giải quyết vấn đề?

? chỉ là một phím tắt định lượng cho thuận tiện, vì vậy

Chỉ cần sử dụng phiên bản dài của bộ định lượng{0,1} , có nghĩa là "tối thiểu 0 lần xuất hiện tối đa 1":

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

1
+1 trang này bắt đầu là một nơi rất tốt để thu thập các thủ thuật regex để giữ trong tâm trí chúng ta.
ppeterka

1
@ppeterka, tôi thực sự sẽ gọi tất cả các câu trả lời khác là "thủ thuật", nhưng câu trả lời của tôi chỉ là sử dụng phiên bản dài của bộ định lượng chứ không phải phím tắt.
stema

3
Không có ý xúc phạm, chỉ là trong từ điển của tôi, sử dụng phiên bản dài của một biểu thức thay vì đường cú pháp ngắn hơn, thuận tiện hơn, người ta cũng coi đó là một mánh khóe ...
ppeterka

8

Một vài cách khác đáng để thêm vào sách lừa RegEx :

Trước tiên, bạn có thể nén RegEx của mình thành: /(<br\s*/?>)+/ivà thay thế bằng <br />(không cần phải tạo gánh nặng cho RegExP bằng giao diện) và bạn sẽ luôn kết thúc với ngắt dòng XHMTL đã chọn.

Các cách khác để sửa đổi RegEx của bạn để nó không bị ngắt */kết thúc bình luận hoặc ?>kết thúc tập lệnh:

  • Sử dụng các bộ lượng hóa sở hữu : #(<br\s*+/?+>)+#i- về cơ bản có nghĩa là \s*+nếu bạn tìm thấy khoảng trắng khớp với số lượng có và giữ nó, và /?+nếu bạn tìm thấy dấu gạch chéo hãy giữ nó!
  • Kèm theo \s*/*trong các nhóm chụp =>#(<br(\s*)(/?)>)+#i

Bản trình diễn trực tiếp: http://codepad.viper-7.com/YjqUbi

Và vì chúng tôi đã nghiêng về hành vi sở hữu, RegEx nhanh nhất cũng bỏ qua vấn đề bình luận là: bản demo được giải thích#(<br\s*+/?+>)++#i


Đối với bình luận trong các tình huống khó khăn

Khi bạn không thể thay đổi mã hoặc đã sử dụng một nhận xét nhiều dòng và:

1. Sử dụng nowdoc :

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

Mã trực tiếp: http://codepad.viper-7.com/22uOtV

Lưu ý: nowdoc tương tự như heredoc nhưng nó không phân tích nội dung và phải có dấu phân cách bắt đầu được đặt trong 'dấu ngoặc đơn '( lưu ý rằng dấu phân cách kết thúc không thể được xác định , phải được theo sau ;và một dòng mới ! )

2. Nhảy qua mã bằng một goto :

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

Ví dụ trực tiếp: http://codepad.viper-7.com/UfqrIQ

3. Nhảy qua mã bằng if(false)hoặc if(0):

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

Kiểm tra: http://codepad.viper-7.com/wDg5H5

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.