【问题标题】:Regex to match word ending OR beginning with a hyphen正则表达式匹配以连字符结尾或开头的单词
【发布时间】:2021-10-18 12:17:19
【问题描述】:

我正在尝试创建一个正则表达式,它会删除以连字符开头或结尾的任何单词(不是两者)。

word1- -> 移除 -word2 -> 删除 sub-word ->保持

我的尝试如下:

def begin_end_hyphen_removal(line):
    return re.sub(r"((\s+|^)(-[A-Za-z]+)(\s+|$))|((\s+|^)([A-Za-z]+-)(\s+|$))","",line)

但是,当我尝试将其应用于以下行时:

here are some word sub-words -word1 word2- sub-word2 word3- -word4
-word5 example
word6-
word7-
another one -word8
-word9

我再次得到与输出相同的输入。

【问题讨论】:

  • 唯一不清楚的部分是如何处理-some-。我知道它不应该匹配(“删除任何以连字符(不是两者)开头或结尾的单词”)。
  • -sub1-sub2 呢?
  • @WiktorStribiżew 是的,如果它是-some-,我想保留它。谢谢!

标签: python-3.x regex


【解决方案1】:

你可以使用

r'\b(?<!-)[A-Za-z0-9]+-\B|\B-[A-Za-z0-9]+\b(?!-)'
r'\b(?<!-)\w+-\B|\B-\w+\b(?!-)'

请参阅regex demo详情

  • \b(?&lt;!-)\w+-\B - 一个或多个单词字符,前面没有-,然后是一个- 字符,位于字符串末尾或非单词字符之前
  • | - 或
  • \B-\w+\b(?!-) - 一个-,它位于字符串的开头或在一个非单词字符之后,然后是一个或多个不跟- 的单词字符。

Python demo

import re
rx = re.compile( r' *(?:\b(?<!-)\w+-\B|\B-\w+\b(?!-))' )
text = 'here are -some- word sub-words -word1 word2- sub-word2 word3- -word4\n-word5 example\nword6-\nword7-\nanother one -word8\n-word9'
print( rx.sub('', text) )

输出:

here are -some- word sub-words sub-word2
 example


another one

【讨论】:

  • 如果我想包含特殊字符而不仅仅是 [A-Za-z0-9] 怎么办?例如删除类似ms$g-
  • @M.A.G 试试re.sub(r'(?&lt;!\S)(-\S+-)(?!\S)|(?&lt;!\S)-\S+(?![\S-])|(?&lt;![\S-])\S+-(?!\S)', r'\1', text),见this regex demo
  • 它工作得很好,但你知道为什么我的解决方案不能正常工作吗?我很想知道
  • @M.A.G 首先,您的主要模式只匹配字母,但您的字符串也可以包含数字,而且看起来是任何非空白字符。此外,您会在两端消耗空格(\s+^$ 分组),因此您无法匹配连续匹配项。
【解决方案2】:
import re

pattern = r"(?=\S*['-])([a-zA-Z'-]+)"
test_string = '''here are some word sub-words -word1 word2- sub-word2 word3- -word4
-word5 example
word6-
word7-
another one -word8
-word9'''
result = re.findall(pattern, test_string)
print(result)

【讨论】:

  • 添加一些评论会使答案更有价值
【解决方案3】:

您可以在 - 之前或之后重复匹配的单词字符

如果您有用连字符分隔的单词,并且以连字符结尾的单词您也想删除,例如sugar-free-

(?<!\S)(?:-\w+(?:-\w+)*|\w+(?:-\w+)*-)(?!\S)

部分模式匹配:

  • (?&lt;!\S)左边的空白边界
  • (?:非捕获组
    • -\w+(?:-\w+)* 匹配 - 和 word chars,可选地由 - 和 word chars 重复
    • |或者
    • \w+(?:-\w+)*- 匹配可选由- 重复的单词字符和单词字符
  • )关闭非捕获组
  • (?!\S)右边的空白边界

查看regex demoPython demo

注意在您尝试的模式中,您使用\s,但请注意它也可以匹配换行符。

如果您不想删除换行符,可以使用[^\S\n]* 代替\s*

例子

import re

def begin_end_hyphen_removal(line):
    return re.sub(r"\s*(?<!\S)(?:-\w+(?:-\w+)*|\w+(?:-\w+)*-)(?!\S)", "", line)


s = ("here are some word sub-words -word1 word2- sub-word2 word3- -word4\n"
     "-word5 example\n"
     "word6-\n"
     "word7-\n"
     "another one -word8\n"
     "-word9")
print(begin_end_hyphen_removal(s))

输出

here are some word sub-words sub-word2 example
another one

【讨论】:

    猜你喜欢
    • 2021-09-26
    • 1970-01-01
    • 2020-02-06
    • 2015-04-27
    • 1970-01-01
    • 1970-01-01
    • 2016-12-07
    • 2017-09-12
    • 1970-01-01
    相关资源
    最近更新 更多