2013-07-11 30 views
5

Về cơ bản, tôi cần biểu thức regex để khớp với tất cả các chuỗi được trích dẫn đôi bên trong các thẻ PHP mà không có biến bên trong.Regex để đối sánh các chuỗi được trích dẫn kép mà không có biến bên trong các thẻ php

Dưới đây là những gì tôi có cho đến nay:

"([^\$\n\r]*?)"(?![\w ]*') 

và thay thế bằng:

'$1' 

Tuy nhiên, điều này sẽ phù hợp với điều bên ngoài thẻ PHP là tốt, ví dụ HTML thuộc tính.

Ví dụ trường hợp:

<a href="somelink" attribute="value">Here's my "dog's website"</a> 
<?php 
    $somevar = "someval"; 
    $somevar2 = "someval's got a quote inside"; 
?> 
<?php 
    $somevar3 = "someval with a $var inside"; 
    $somevar4 = "someval " . $var . 'with concatenated' . $variables . "inside"; 
    $somevar5 = "this php tag doesn't close, as it's the end of the file..."; 

nó phải phù hợp và thay thế tất cả những nơi mà " nên được thay thế bằng một ', điều này có nghĩa rằng các thuộc tính html lý tưởng nên bị bỏ lại một mình.

Ví dụ đầu ra sau khi thay thế:

<a href="somelink" attribute="value">Here's my "dog's website"</a> 
<?php 
    $somevar = 'someval'; 
    $somevar2 = 'someval\'s got a quote inside'; 
?> 
<?php 
    $somevar3 = "someval with a $var inside"; 
    $somevar4 = 'someval ' . $var . 'with concatenated' . $variables . 'inside'; 
    $somevar5 = 'this php tag doesn\'t close, as it\'s the end of the file...'; 

Nó cũng sẽ là tuyệt vời để có thể phù hợp với bên trong kịch bản thẻ quá ... nhưng điều đó có thể đẩy nó cho một regex thay thế.

Tôi cần phương pháp tiếp cận regex, không phải là cách tiếp cận PHP. Giả sử tôi đang sử dụng regex-replace trong trình soạn thảo văn bản hoặc JavaScript để dọn sạch mã nguồn PHP.

+1

Sử dụng 'preg_replace_callback()' để khớp các thẻ php và trong gọi lại sử dụng cụm từ thông dụng của bạn. – HamZa

+0

@HamZa Điều gì xảy ra nếu có một cái gì đó như thế này trong php: '$ a = ' '; '? – hek2mgl

+1

@ hek2mgl Bạn có thể cho tôi biết cơ hội xảy ra trong bối cảnh chung không? – HamZa

Trả lời

5

Dưới đây là một chức năng mà sử dụng phần mở rộng tokenizer để áp dụng preg_replace để PHP chỉ chuỗi:

function preg_replace_php_string($pattern, $replacement, $source) { 
    $replaced = ''; 
    foreach (token_get_all($source) as $token) { 
     if (is_string($token)){ 
      $replaced .= $token; 
      continue; 
     } 
     list($id, $text) = $token; 
     if ($id === T_CONSTANT_ENCAPSED_STRING) { 
      $replaced .= preg_replace($pattern, $replacement, $text); 
     } else { 
      $replaced .= $text; 
     } 
    } 
    return $replaced; 
} 

Để đạt được những gì bạn muốn, bạn có thể gọi nó như thế này:

<?php 
    $filepath = "script.php"; 
    $file = file_get_contents($filepath); 
    $replaced = preg_replace_php_string('/^"([^$\{\n<>\']+?)"$/', '\'$1\'', $file); 
    echo $replaced; 

Các biểu thức chính quy được chuyển như đối số đầu tiên là chìa khóa ở đây. Nó nói với các chức năng để chỉ chuyển đổi chuỗi để đương đơn trích dẫn của họ nếu họ không chứa $(nhúng biến "$a"), {(nhúng biến loại 2 "{$a[0]}"), một dòng mới, < hoặc > (tag cuối HTML/mở biểu tượng). Nó cũng kiểm tra xem chuỗi có chứa một dấu nháy đơn hay không, và ngăn chặn sự thay thế để tránh các tình huống mà nó cần phải được thoát.

Trong khi đây là giải pháp PHP, đây là giải pháp chính xác nhất. Gần nhất bạn có thể nhận được với bất kỳ ngôn ngữ nào khác sẽ yêu cầu bạn xây dựng trình phân tích cú pháp PHP của riêng bạn trong ngôn ngữ đó ở một mức độ nào đó để giải pháp của bạn chính xác.

+0

Đây là một cách tiếp cận thú vị nhưng tôi e rằng tôi không thể sử dụng PHP cho những gì tôi cần! –

+2

Bạn đang sử dụng ngôn ngữ nào? – hek2mgl

6

tl; dr

Đây thực sự là phức tạp phức tạp để thực hiện với regex. Đặc biệt không phải là một regex đơn giản. Bạn có thể có may mắn hơn với regex lồng nhau, nhưng bạn thực sự cần phải lex/phân tích cú pháp để tìm chuỗi của mình và rồi bạn có thể hoạt động trên chúng bằng regex.

Giải thích

Bạn có thể lẽ quản lý để làm điều này. Bạn có thể có lẽ thậm chí còn quản lý để làm điều này tốt, thậm chí có thể hoàn hảo. Nhưng nó sẽ không dễ dàng. Nó sẽ rất rất khó khăn.

Hãy xem xét điều này:

Welcome to my php file. We're not "in" yet. 

<?php 
    /* Ok. now we're "in" php. */ 

    echo "this is \"stringa\""; 
    $string = 'this is \"stringb\"'; 
    echo "$string"; 
    echo "\$string"; 

    echo "this is still ?> php."; 

    /* This is also still ?> php. */ 

?> We're back <?="out"?> of php. <?php 

    // Here we are again, "in" php. 

    echo <<<STRING 
    How do "you" want to \""deal"\" with this STRING; 
STRING; 

    echo <<<'STRING' 
    Apparently this is \\"Nowdoc\\". I've never used it. 
STRING; 

    echo "And what about \\" . "this? Was that a tricky '\"' to catch?"; 

    // etc... 

Quên phù hợp với tên biến trong chuỗi trích dẫn kép. Bạn có thể khớp tất cả chuỗi trong ví dụ này không? Trông như một cơn ác mộng đối với tôi. Nhấn mạnh cú pháp của SO chắc chắn sẽ không biết phải làm gì với nó.

Bạn có cho rằng các biến có thể xuất hiện trong các chuỗi heredoc không?

Tôi không muốn nghĩ về regex để kiểm tra xem:

  1. Bên <?php hoặc <?= đang
  2. Không trong một chú thích
  3. Bên trong một báo trích dẫn
  4. loại gì về trích dẫn Trích dẫn?
  5. Đây có phải là báo giá của loại đó không?
  6. Có phải trước \ (đã thoát) không?
  7. Có phải là \ đã thoát không ??
  8. vv ...

Tóm tắt

Bạn có thể viết một regex cho việc này. Bạn có thể quản lý với một số backreferences và rất nhiều thời gian và chăm sóc. Nó sẽ khó khăn và có lẽ bạn sẽ lãng phí rất nhiều thời gian, và nếu bạn cần sửa chữa nó, bạn sẽ không hiểu regex bạn đã viết.

Xem thêm

This answer. Nó đáng giá.

Các vấn đề liên quan