簡體   English   中英

PHP PCRE正則表達式優化

[英]php PCRE Regex optimization

對於正則表達式而言,這是一個相當新的東西,我正在嘗試優化它,或者至少知道是否有更好的方法來做到這一點。

這是我的輸入字符串:

$str = 'Some text
spanned on
several lines
txt_to_grab1 fixed_text1 txt_to_grab2
Full line to grab
txt_to_grab3 fixed_text2 txt_to_grab4
Some text after';

我正在嘗試抓住從“ txt_to_grab1”到“ txt_to_grab4”的行,但只有單詞“ txt_to_grabX”和行“ Full line to抓住”。
我想保留之前和之后未觸及的所有內容(即換行符),但要刪除我抓取的行內的換行符(因為每行將是一個將進入html表的<tr> )。

我發現匹配的正則表達式模式/替換:

$find = "#(?<=\n)(.*?) fixed_text1 (.*?)(\n.*?\n)(.*?) fixed_text2 (.*?)(\n)#i";
$replace = '"$1" && "$2" grabbed.$3"$4" && "$5" grabbed.$6';   

$find = "#(.*)(?<=\n)(.*?) fixed_text1 (.*?)(\n)(.*)(?<=\n)(.*?) fixed_text2 (.*?)(\n.*)#is";
$replace = '$1"$2" && "$3" grabbed.$4$5"$6" && "$7" grabbed.$8';

問題:

所有問題可以歸納為:是否存在更好/更短/更快的模式?

  • 如何使模式與\\ r \\ n或\\ n一起使用? 我在堆棧上的某個地方讀到(\\ r?\\ n)將是一個解決方案,但我不知道如何在lookbehinds中使用它們。 例如,以下模式可以工作,但我不喜歡它們(在lookbehinds中僅使用\\ n很臟,可能會產生意外的結果):

     "#(?<=\\n)(.*?) fixed_text1 (.*?)(\\r?\\n.*?\\r?\\n)(.*?) fixed_text2 (.*?)(\\r?\\n)#i" "#(.*)(?<=\\n)(.*?) fixed_text1 (.*?)(\\r?\\n)(.*)(?<=\\n)(.*?) fixed_text2 (.*?)(\\r?\\n.*)#is"; 
  • 甚至更好的是,如何使用“ s”修飾符從模式中刪除所有換行符,因此能夠使用(。*?)但仍能抓住我想要的東西? 單詞邊界?

  • 多行模式(m修飾符)在這里有用/有用嗎?

如果您提供一些正則表達式,我真的很想解釋它。

您無需為此而煩惱。 只需在正則表達式的開頭使用行首錨,然后在末尾使用行尾錨(在多行模式下$ ^$ )。 要匹配中間的行分隔符,您可以使用(?:\\r\\n|[\\r\\n]) ,這是三種最常見的行分隔符樣式的慣用法: \\n\\r\\r\\n

至於s修飾符(又稱“單行”或“ DOT_ALL”),您也不需要。 它所做的只是允許點元字符與行分隔符以及所有其他字符匹配,這對您沒有任何好處。 希望它在到達換行符時停止匹配,因此可以將其從捕獲中排除。

這是一個演示:

$pattern='#^(.*?) fixed_text1 (.*)(?:\r\n|[\r\n])(.*)(?:\r\n|[\r\n])(.*?) fixed_text2 (.*)$#im';

preg_match($pattern, $source, $m);

echo "$m[1] && $m[2] grabbed.\n";
echo "$m[3]\n";
echo "$m[4] && $m[5] grabbed.\n"; 

輸出:

txt_to_grab1 && txt_to_grab2 grabbed.
Full line to grab
txt_to_grab3 && txt_to_grab4 grabbed.

在ideone.com上查看其運行情況

暫無
暫無

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

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