6

尝试用锚标记替换所有出现的@提及,到目前为止我有:

$comment = preg_replace('/@([^@ ])? /', '<a href="/$1">@$1</a> ', $comment);

采用以下示例字符串:

"@name kdfjd fkjd as@name @ lkjlkj @name"

到目前为止一切正常,但我想忽略那个单一的“@”符号。我尝试在“[^@]”之后使用“+”和“{2,}”,我认为这会强制执行最少数量的匹配,但它不起作用。

4

6 回答 6

10

替换问号 ( ?) 量词(“可选”)并+在您的字符类别后添加一个(“一个或多个”):

@([^@ ]+)
于 2012-04-30T13:02:30.480 回答
7

正则表达式

(^|\s)(@\w+)

可能是你所追求的。

它基本上意味着,行首或空格,然后是 @ 符号,后跟 1 个或多个单词字符。

例如

preg_match_all('/(^|\s)(@\w+)/', '@name1 kdfjd fkjd as@name2 @ lkjlkj @name3', $result);
var_dump($result[2]);

给你

Array
    (
        [0] => @name1
        [1] => @name3
    )
于 2012-04-30T13:08:49.787 回答
4

我喜欢 Petah 的回答,但我稍微调整了一下

preg_replace('/(^|\s)@([\w.]+)/', '$1<a href="/users/$2">@$2</a>', $text);

主要区别在于:

  • @符号不包括在内。仅用于显示,不应在 URL 中
  • 允许.字符(注意:\w包括下划线)
  • 在替换中,我$1在开头添加以保留空格
于 2015-09-30T02:44:42.083 回答
3

替换?+将起作用,但不像您期望的那样。

@name您的表达式在字符串末尾不匹配。

$comment = preg_replace('#@(\w+)#', '<a href="/$1">$0</a> ', $comment);

这应该做你想要的。\w+代表字母 (a-zA-Z0-9)

于 2012-04-30T13:16:33.077 回答
1

我建议在匹配@当时的一个或多个不是空格或@.

“一个或多个”量词 ( +)可防止匹配未提及 one 的提及

使用lookbehind 是一个好主意,因为它不仅可以防止匹配电子邮件地址和其他此类不需要的子字符串,它还要求正则表达式引擎主要搜索@s 然后检查前面的字符。这应该会提高模式性能,因为空格的数量应该始终超过评论中提及的数量。

如果输入文本是多行或可能包含换行符,则添加m模式修饰符将告诉^匹配所有行开头。如果可以使用换行符和制表符,则 is 使用起来会更可靠(?<=^|\s)@([^@\s]+)

代码:(演示

$comment = "@name kdfjd @@ fkjd as@name @ lkjlkj @name";

var_export(
    preg_replace(
        '/(?<=^| )@([^@ ]+)/',
        '<a href="/$1">@$1</a>',
        $comment
    )
);

输出:(单引号来自var_export()

'<a href="/name">@name</a> kdfjd @@ fkjd as@name @ lkjlkj <a href="/name">@name</a>'
于 2020-12-10T21:08:19.910 回答
0

尝试:

'/@(\w+)/i'

于 2012-04-30T13:03:18.557 回答