替换子字符串的正则表达式(如果不是单词的开头)

Regex to replace substring (if not the start of a word)

我正在处理像 @Alice @ home 这样的推文。我想将用户提及转换为普通词(例如 @Alice => Alice,但保留 个人 @ 作为 at 的替代项。所以简单地替换所有出现的 @ 是行不通的。

我发现了单词边界的概念,但我无法让它们为此工作。一方面,

print re.sub(r'\b@\b', '', '@Alice @ home')

没有任何改变,而

print re.sub(r'\bAlice\b', '', '@Alice @ home')

结果为 @ @ home。所以我假设 at 符号 (@) 不算作单词的一部分。

简而言之,我基本上是在寻找 pattern 这样

print re.sub(pattern, '', '@Alice @ home')

输出Alice @ home.

感谢任何提示。

您可以玩弄边界 \B\b

>>> print re.sub(r'\B@\b', r'', '@Alice @ home')
Alice @ home
>>> print re.sub(r'\B@\b', r'', 'foo @Alice @ home')
foo Alice @ home

\B 匹配两个单词字符或两个非单词字符。因此,上述正则表达式中的 \B@ 匹配 Alice 之前的 @ 和另一个单独的 @ 符号。 \b 匹配单词字符和非单词字符(反之亦然)。所以下面的 \b 使模式只匹配第一个,因为第一个 @ 本身后跟一个单词字符,即 A

对我来说最简单的工作方式:

>>> s = '@Alice @ home'
>>> re.sub('\s@\s', ' at ', s).replace('@', '')
'Alice at home'

初始答案

试试下面的正则表达式:

@(?! )

以下是它如何执行的几个示例:

>>> print re.sub(r'@(?! )', '', '@Alice @ home')
Alice @ home
>>> print re.sub(r'@(?! )', '', 'Whatever @Alice @ home')
Whatever Alice @ home

您也可以使用 a related regex fiddle 进行测试。

要点:

  • @at 符号
  • (?! ) – 否定前瞻匹配除 space 之外的任何内容(即 后面没有 space

就我个人而言,我发现零宽度字边界断言(\b\B)有点让人分心,我更喜欢使用 zero-width lookarounds 来处理这种事情,但是 TMTOWTDI。

关于脸

我(像往常一样)更多地考虑了这一点,并且我发现公认的零宽度字边界断言的简单性和字符串开始和结束匹配的令人信服的案例。

考虑一组更完整的可以想象的推文:

@Alice @ home
Whatever @Alice @ home
What're you lookin' @
What're you lookin' @?

事实证明,要使这些正确,需要更复杂的负前瞻,将我最初的正则表达式变成:

@(?![ \W]|$)

和以前一样,下面是它如何执行的示例:

>>> print re.sub(r'@(?![ \W]|$)', '', '@Alice @ home')
Alice @ home
>>> print re.sub(r'@(?![ \W]|$)', '', 'Whatever @Alice @ home')
Whatever Alice @ home
>>> print re.sub(r'@(?![ \W]|$)', '', "What're you lookin' @")
What're you lookin' @
>>> print re.sub(r'@(?![ \W]|$)', '', "What're you lookin' @?")
What're you lookin' @?

和以前一样,您也可以使用 a related regex fiddle 进行测试。

但是 像 Avinash Raj 这样的词边界模式使这组更完整的可以想象的推文正确...没有那么大张旗鼓:

>>> print re.sub(r'\B@\b', '', '@Alice @ home')
Alice @ home
>>> print re.sub(r'\B@\b', '', 'Whatever @Alice @ home')
Whatever Alice @ home
>>> print re.sub(r'\B@\b', '', "What're you lookin' @")
What're you lookin' @
>>> print re.sub(r'\B@\b', '', "What're you lookin' @?")
What're you lookin' @?

如果您也喜欢,请使用 another related regex fiddle 进行测试。

最重要的是,这对我来说是一次很酷的学习经历,可以质疑我倾向于使用的东西,我希望你也有同样的感受:继续我们的词边界断言冒险! :)

(?:^|(?<=\s))@(?!\s)

尝试 this.This 将仅从 word.if 的开头替换 @ @ 位于单词的中间,例如 as@sas 它将节省 it.See演示。

https://regex101.com/r/tX2bH4/44

re.sub(r'(?:^|(?<=\s))@(?!\s)','',s)