引号之间的井号

hashtages between quotation marks

我正在编写这个小代码。我设法让它在一侧使用双引号,但在另一侧不使用:

/(?<!\S)#([0-9\p{L}]+)+(?=[\s,!?.\n][^"]|$)/

我的意思是:https://regex101.com/r/yN4tJ6/307

最后一个 " #action 不应转换为主题标签。如何将此功能添加到上面的代码中?

这个表达式似乎有效:

(?<!\S)(?<!".)#([0-9\p{L}]+)+(?=[\s,!?.\n][^"]|$)

DEMO

我的猜测是您可能想设计一个类似于以下的表达式:

(?<!"\s)#([0-9\p{L}]+)(?=[\s,!?.\n][^"]|$)

表达式在 regex101.com, if you wish to explore/simplify/modify it, and in this link 的右上面板进行了解释,如果您愿意,您可以观察它如何与一些示例输入匹配。

测试

$re = '/(?<!"\s)#([0-9\p{L}]+)(?=[\s,!?.\n][^"]|$)/m';
$str = 'I enjoy #action movies! #Action
movies are #cool.

Color #000000;  #ffffff; work fine

<div style=" #something "> - works

#action " - works

" #action  - doesn\'t work


';

preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);

var_dump($matches);

你当前模式的问题,几乎可以工作,是你需要一个可变宽度的 lookbehind 来正确检查双引号 before 的 presence/absence每个标签。我采用的方法是将 preg_match_all 与一种模式一起使用,该模式仅消耗足够的信息来决定主题标签是否匹配。考虑以下脚本:

preg_match_all('/(?:^|[^"]\s+)(#[0-9\p{L}]+)[.;,!?]?(?=$|\s+[^"])/', $input, $matches);
print_r($matches[1]);

 Array
(
    [0] => #action
    [1] => #Action
    [2] => #cool
    [3] => #000000
    [4] => #ffffff
)

这里是对模式的解释:

(?:^|[^"]\s+)   match the start of the input, OR
                a single non quote character, followed by one or more whitespaces
(#[0-9\p{L}]+)  then match and capture a hashtag
[.;,!?]?        followed by an optional punctuation character
(?=$|\s+[^"])   finally lookahead and assert either the end of the input, OR
                one or more whitespaces followed by a single non quote character

请注意,虽然我们确实匹配了一些我们并不真正想要的内容,但这并不重要,因为第一个捕获组只包含主题标签。