簡體   English   中英

PHP:正則表達式忽略引號內的轉義引號

[英]PHP: Regex to ignore escaped quotes within quotes

我在發布之前查看了相關問題,但我無法修改任何相關答案以使用我的方法(不擅長正則表達式)。

基本上,這是我現有的線路:

$code = preg_replace_callback( '/"(.*?)"/', array( &$this, '_getPHPString' ), $code );

$code = preg_replace_callback( "#'(.*?)'#", array( &$this, '_getPHPString' ), $code );

它們都匹配包含在''""之間''字符串。 我需要正則表達式來忽略它們之間包含的轉義引號。 因此''之間''數據將忽略\\'""之間的數據將忽略\\"

任何幫助將不勝感激。

對於大多數字符串,您需要允許轉義任何內容(不僅僅是轉義引號)。 例如,您很可能需要允許像"\\n""\\t"這樣的轉義字符,當然還有轉義符: "\\\\"

這是一個常見問題,很久以前就已解決(和優化)。 Jeffrey Friedl 在他的經典著作《 掌握正則表達式(第 3 版)》中(作為示例)深入探討了這個問題。 這是您正在尋找的正則表達式:

好的:

"([^"\\\\]|\\\\.)*"
版本 1:工作正常但效率不高。

更好的:

"([^"\\\\]++|\\\\.)*""((?>[^"\\\\]+)|\\\\.)*"
版本 2:如果您有所有格量詞或原子組,效率會更高(請參閱:使用原子組方法的 sin 正確答案)。

最好的事物:

"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"
版本 3:效率更高。 實現 Friedl 的: “展開循環”技術。 不需要所有格或原子組(即這可以在 Javascript 和其他功能較少的正則表達式引擎中使用。)

以下是雙引號和單引號子字符串的 PHP 語法中推薦的正則表達式:

$re_dq = '/"[^"\\\\]*(?:\\\\.[^"\\\\]*)*"/s';
$re_sq = "/'[^'\\\\]*(?:\\\\.[^'\\\\]*)*'/s";

試試這樣的正則表達式:

'/"(\\\\[\\\\"]|[^\\\\"])*"/'

一個(簡短的)解釋:

"                 # match a `"`
(                 # open group 1
  \\\\[\\\\"]     #   match either `\\` or `\"`
  |               #   OR
  [^\\\\"]        #   match any char other than `\` and `"`
)*                # close group 1, and repeat it zero or more times
"                 # match a `"`

以下片段:

<?php
$text = 'abc "string \\\\ \\" literal" def';
preg_match_all('/"(\\\\[\\\\"]|[^\\\\"])*"/', $text, $matches);
echo $text . "\n";
print_r($matches);
?>

產生:

abc "string \\ \" literal" def
Array
(
    [0] => Array
        (
            [0] => "string \\ \" literal"
        )

    [1] => Array
        (
            [0] => l
        )

)

正如您在Ideone 上看到的那樣

這有可能:

/"(?>(?:(?>[^"\\\\]+)|\\\\.)*)"/

/'(?>(?:(?>[^'\\\\]+)|\\\\.)*)'/

基於一些粗略的基准測試,這似乎與展開循環一樣快,但更容易閱讀和理解。 它首先不需要任何回溯。

"[^"\\]*(\\.[^"\\]*)*"

這將把引號留在外面

(?<=['"])(.*?)(?=["'])

並使用global /g 將匹配所有組

根據W3資源: https : //www.w3.org/TR/2010/REC-xpath20-20101214/#doc-xpath-StringLiteral

一般的正則表達式是:

"(\\.|[^"])*"

(+捕獲組第一次檢查時不需要加反斜杠)

解釋:

  • "..."引號之間的任何匹配
  • (...)*內部可以有從 0 到 Infinity 的任意長度
  • \\\\.|[^"]首先接受任何后面有斜杠的字符 | (或) 然后接受任何不是引號的字符

PHP 版本的正則表達式具有更好的分組功能,可以更好地處理Any Quotes可以是這樣的:

<?php
    $str='"First \\" \n Second" then \'This \\\' That\'';
    echo $str."\n";
    // "First \" \n Second" then 'This \' That'

    $RX_inQuotes='/"((\\\\.|[^"])*)"/';
    preg_match_all($RX_inQuotes,$str,$r,PREG_SET_ORDER);
    echo $r[0][1]."\n";
    // First \" \n Second

    $RX_inAnyQuotes='/("((\\\\.|[^"])*)")|(\'((\\\\.|[^\'])*)\')/';
    preg_match_all($RX_inAnyQuotes,$str,$r,PREG_SET_ORDER);
    echo $r[0][2]." --- ".$r[1][5];
    // First \" \n Second --- This \' That
?>

試試看: http : //sandbox.onlinephpfunctions.com/code/4328cc4dfc09183f7f1209c08ca5349bef9eb5b4

重要提示:在這個時代,對於不確定的內容,您必須在正則表達式的末尾使用u標志,如/.../u以避免破壞multi-byte字符串(如UTF-8 )或函數(如mb_ereg_match )

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM