2012-10-07 60 views
0

我想匹配一個半動態生成的字符串。所以我可以看看它的格式是否正確,然後從中提取我需要的信息。我的問題是,無論我多麼努力地掌握正則表達式,無法理解它爲我的生活。即使有所謂的發電機的幫助。正則表達式援助

我所擁有的是一對不同的字符串,如下所示。 [@img:1234567890][@user:1234567890][@file:file_name-with.ext]。像這樣傳遞的字符串意圖通過一個過濾器,以便它們可以替換爲鏈接和更可讀的名稱。但再次嘗試,因爲我可能不能爲任何給定的任何一個提出正則表達式。

我在查找格式:[@word:]其中我將從字符串中去掉[,],@和單詞,這樣我就可以相應地查詢我的數據庫,無論它是什麼並相應地使用它。只是正則表達式阻止了我。

+0

試試'@(\ w +)(。*) ]'。 '$ 1'和'$ 2'會給你你的變量。 – Virendra

+1

請注意,您應該使用[摘要作爲問題標題](http://stuck.include-once.org/#help7)。如果你在那裏更具體,它會更容易找到其他人,並吸引更多的具體幫助,而不是隻有任何人對神祕頭條感興趣。避免重複標籤,多餘的請求幫助,沒有問題的問號。 – mario

回答

1

不確定你是什麼意思的發電機。我總是使用在線匹配器來查看我的測試案例。 @Virendra幾乎沒有忘記逃離[]字符。

/\[@(\w+):(.*)\]/ 

您需要以正則表達式分隔符開始和結束,在本例中爲'/'字符。

然後我們逃過正則表達式使用的'[]'來匹配字符範圍,因此'['。

接下來我們匹配一個文字'@'符號。

現在我們要保存這個下一個匹配,所以我們可以稍後使用它,所以我們用()包圍它。

\w匹配word。基本上任何不是空格,標點符號或行字符的字符。

再次匹配文字:

也許有用的第二部分在一個比賽組中,所以(.*)將匹配任何次數的任何字符,併爲您保存。

然後我們像前面所做的那樣逃過了收盤]。我們可以用preg_match來將匹配保存到一個數組中。

$pattern = '/\[@(\w+):(.*)\]/'; 
$subject = '[@user:1234567890]'; 
preg_match($pattern, $subject, $matches); 
print_r($matches); 

將輸出

array(
    [0] => '[@user:1234567890]', // Full match 
    [1] => 'user', // First match 
    [2] => '1234567890' // Second match 
) 

一個特別有用的工具,我發現是txt2re

+0

引用通過谷歌發現的非引用生成器,在那裏你輸入一個字符串,你想匹配和它的suposed產生一個正則表達式。其中大多數不是從我收集的東西,或者他們只匹配你給的字符串,並且沒有足夠的空間來玩 – chris

+0

要分別獲得$ 1和$ 2,我會使用preg_match,preg_replace,other?如果你不得不建議一些東西? – chris

+1

@chris爲'preg_match'添加了部分 – Brombomb

0

你可以嘗試這樣的事情:

/\[@(\w+):([^]]*)\]/ 

\[轉義字符[(否則解釋爲一個字符集); \w表示任何「單詞」字符,並且[^]]*表示任何非]字符(爲了避免匹配超過標籤的末尾,因爲.*可能)。在括號組相匹配的各種部件,這樣就可以使用$1$2preg_replace生成替換文本:

echo preg_replace('/\[@(\w+):([^]]*)\]/', '$1 $2', '[@link:abcdef]'); 

打印link abcdef

1

這就是我會做。

<pre> 
<?php 

    $subj = 'An image:[@img:1234567890], a user:[@user:1234567890] and a file:[@file:file_name-with.ext]'; 
    preg_match_all('~(?<match>\[@(?<type>[^:]+):(?<value>[^\]]+)\])~',$subj,$matches,PREG_SET_ORDER); 
    foreach ($matches as &$arr) unset($arr[0],$arr[1],$arr[2],$arr[3]); 
    print_r($matches); 

?> 
</pre> 

這將輸出

Array 
(
    [0] => Array 
     (
      [match] => [@img:1234567890] 
      [type] => img 
      [value] => 1234567890 
     ) 

    [1] => Array 
     (
      [match] => [@user:1234567890] 
      [type] => user 
      [value] => 1234567890 
     ) 

    [2] => Array 
     (
      [match] => [@file:file_name-with.ext] 
      [type] => file 
      [value] => file_name-with.ext 
     ) 

) 

而這裏的我會怎樣使用preg_replace_callback()功能的僞版本:

function replace_shortcut($matches) { 
    global $users; 
    switch (strtolower($matches['type'])) { 
     case 'img' : return '<img src="images/img_'.$matches['value'].'jpg" />'; 
     case 'file' : return '<a href="files/'.$matches['value'].'" target="_blank">'.$matches['value'].'</a>'; 
     // add id of each user in array 
     case 'user' : $users[] = (int) $matches['value']; return '%s'; 
     default : return $matches['match']; 
    } 
} 

$users = array(); 
$replaceArr = array(); 

$subj = 'An image:[@img:1234567890], a user:[@user:1234567890] and a file:[@file:file_name-with.ext]'; 
// escape percentage signs to avoid complications in the vsprintf function call later 
$subj = strtr($subj,array('%'=>'%%')); 
$subj = preg_replace_callback('~(?<match>\[@(?<type>[^:]+):(?<value>[^\]]+)\])~',replace_shortcut,$subj); 

if (!empty($users)) { 

    // connect to DB and check users 
    $query = " SELECT `id`,`nick`,`date_deleted` IS NOT NULL AS 'deleted' 
       FROM `users` WHERE `id` IN ('".implode("','",$users)."')"; 
    // query 
    // ... 
    // and catch results 
    while ($row = $con->fetch_array()) { 
     // position of this id in users array: 
     $idx = array_search($row['id'],$users); 
     $nick = htmlspecialchars($row['nick']); 
     $replaceArr[$idx] = $row['deleted'] ? 
      "<span class=\"user_deleted\">{$nick}</span>" : 
      "<a href=\"users/{$row['id']}\">{$nick}</a>"; 
     // delete this key so that we can check id's not found later... 
     unset($users[$idx]); 
    } 
    // in here: 
    foreach ($users as $key => $value) { 
     $replaceArr[$key] = '<span class="user_unknown">User'.$value.'</span>'; 
    } 
    // replace each user reference marked with %s in $subj 
    $subj = vsprintf($subj,$replaceArr); 

} else { 

    // remove extra percentage signs we added for vsprintf function 
    $subj = preg_replace('~%{2}~','%',$subj); 

} 
unset($query,$row,$nick,$idx,$key,$value,$users,$replaceArr); 

echo $subj; 
+0

這是一個很好的觀點,我甚至沒有考慮過具有倍數的字符串。 – chris

+1

您可能還想使用'preg_replace_callback()'來重新設置這些值的格式,而不是用'preg_match_all()'來捕獲它們。 – inhan