我正在尝试匹配半动态生成的字符串。所以我可以看看它是否是正确的格式,然后从中提取我需要的信息。我的问题是,无论我多么努力地抓住正则表达式,我都无法理解它的生命。即使在所谓的发电机的帮助下。
我所拥有的是几个不同的字符串,如下所示。 [@img:1234567890]
以及[@user:1234567890]
和[@file:file_name-with.ext]
。像这样的字符串传递意图通过过滤器,因此可以用链接和更可读的名称替换它们。但是再次尝试,因为我可能无法为任何给定的一个提出正则表达式。
我正在寻找格式:[@word:]
我将从字符串中删除[,],@和word,这样我就可以相应地转换查询我的数据库,无论它是什么,并使用因此。只是正则表达式让我退缩。
答案 0 :(得分: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
答案 1 :(得分: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;
答案 2 :(得分:0)
您可以尝试这样的事情:
/\[@(\w+):([^]]*)\]/
\[
转义[
字符(否则解释为字符集); \w
表示任何“单词”字符,[^]]*
表示任何非]
字符(以避免匹配标记的末尾,如.*
可能)。 parens对各个匹配的部分进行分组,以便您可以使用$1
中的$2
和preg_replace
来生成替换文字:
echo preg_replace('/\[@(\w+):([^]]*)\]/', '$1 $2', '[@link:abcdef]');
打印link abcdef