我试图寻找一段时间的答案,但找不到它。有许多与匹配文本相关的帖子,其中没有某些文本,但似乎没有一个文章适用于+匹配的情况,但只有在单个+(例如。++)之前才允许这样做
我正在尝试从文本中删除标点符号,但让两个连续的++符号保留,但单个+符号消失
$text="Hello World! C+ C++ C#";
print_r(preg_replace('/(?!\+\+)[[:punct:]]/', ' ', $text));
结果(我不知道为什么后者+会被删除?有人可以解释一下吗?):
Hello World C C + C
如果我尝试:
$text="Hello World! C+ C++ C#";
print_r(preg_replace('/(?!\+)[[:punct:]]/', ' ', $text));
结果是:
Hello World C + C ++ C
但我想要的结果是:
Hello World C C ++ C
由于
更新:我意识到我应该提到我会有其他我想避免的角色。我可能过分简化了这个问题。例如,我可能想要避免#也因此结果将是
Hello World C C ++ C#
解决方案应该易于扩展。对于这些遗漏信息造成的不便,我感到很遗憾。
答案 0 :(得分:3)
这里有几个选择,一个是:
(?<!\+)[+#](?!\+)
# with lookarounds making sure no + is after/behind
PHP
:
<?php
$regex = '~(?<!\+)[+#](?!\+)~';
$string = 'Hello World! C+ C++ C#';
$string = preg_replace($regex, '', $string);
echo $string;
?>
<小时/> 另一种方法是使用
(*SKIP)(*FAIL)
机制(在本例中速度稍快):
\+{2}(*SKIP)(*FAIL)|[+#]
# let two consecutive ++ always fail
在regex101.com as well上查看此演示文稿。
最后但并非最不重要: 如果你想添加应该避免使用的字符/表达式,你可以将它们放在一个非捕获组中,让它失败:
(?:\#|\+{2})(*SKIP)(*FAIL)|
[[:punct:]]
答案 1 :(得分:2)
你的第一个正则表达式(?!\+\+)[[:punct:]]
不起作用,因为它在一个否定中寻找两个连续的+
个符号 - 在每个位置 - 然后断言下一个直接字符是一个标点符号。当它看到C++
时,光标位于第一个+
符号旁边,此匹配会成功,因为在第二个+
之后没有+
。所以首先匹配+
。
Hello World! C+ C+|+ C#
^ Cursor here - (?!\+\+)[[:punct:]] is matched
正则表达式:
[[:punct:]]++((?<=\+)(?<=[^+]\+))
除了条件肯定的后视断言之外,占有式匹配也可以完成这项任务。
说明:
[[:punct:]]++ // Match punctuation marks possessively - won't allow backtrack
((?<=\+) // Start of a conditional statement, check if last match is a `+`
(?<=[^+]\+) // If yes, it should not be preceded by another `+`
) // End of conditional
PHP:
preg_replace('@[[:punct:]]++((?<=\+)(?<=[^+]\+))@', ' ', $text)
<强>更新强>
如果+
首字母前面总是有一些字母,则会有一个更短的解决方案:
\b\+(?!\+)
答案 2 :(得分:2)
第一个代码段的工作方式如下:找到标点符号,如果它不是++
序列的起点,则匹配并删除它。因此,+
中的第二个C++
匹配,并被删除。
您可以使用(*SKIP)(*FAIL)
动词匹配并从匹配项中丢弃您要保留的内容并匹配您要删除的内容:
preg_replace('/\+{2}(*SKIP)(*F)|[[:punct:]]+/', ' ', $text);
添加更多字符 - 以防万一:
preg_replace('/(?:[#^]|\*{3}|\+{2})(*SKIP)(*F)|[[:punct:]]+/', ' ', $text);
^^^ ^
请参阅PHP demo
<强>详情:
\+{2}(*SKIP)(*FAIL)
- 匹配2个+
符号,然后将其从匹配项中丢弃|
- 或[[:punct:]]+
- 匹配一个或多个标点符号。在替换模式中,我们只需用空格替换。
答案 3 :(得分:0)
我认为这里有三种情况可以匹配加号 必须匹配双加号才能超越它。
注意 - 这是关于加号的左右规则。没有规则,但这些。
查找:
[^\P{P}+]|(\+\+)\+|\+
替换:'$1 '
解释
[^\P{P}+] # Punctuation but not plus
|
( \+\+ ) # (1), Plus with leading ++
\+
|
\+ # Any old plus sign
可以减少到
[^\P{P}+] # Punctuation but not plus
|
( \+\+ )? # (1), Plus with optional leading ++
\+