【问题标题】:Using Regex to find words with characters that are the same or that are different使用正则表达式查找字符相同或不同的单词
【发布时间】:2012-05-11 07:01:38
【问题描述】:

我有一个单词列表,例如:

l = """abca
bcab
aaba
cccc
cbac
babb
"""

我想找到首尾相同的单词,并且中间的两个字符与首尾不同。

想要的最终结果:

['abca', 'bcab', 'cbac']

我试过了:

re.findall('^(.)..\\1$', l, re.MULTILINE)

但它也会返回所有不需要的单词。 我想以某种方式使用 [^...] ,但我想不通。 有一种方法可以使用集合(从上面的搜索中过滤结果),但我正在寻找一个正则表达式。

有可能吗?

【问题讨论】:

  • ".*" 是一个很好的正则表达式,用于查找相同或不同的字符。 :)
  • 您有七个答案,所有这些都回答了您的问题(尽管其中两个说“这比正则表达式更好”,我倾向于同意)。你应该接受其中之一。

标签: python regex


【解决方案1】:

编辑: 修正为使用否定的lookahead 断言而不是否定的lookbehind 断言。阅读 cmets 以获得 @AlanMoore 和 @bukzor 的解释。

>>> [s for s in l.splitlines() if re.search(r'^(.)(?!\1).(?!\1).\1$', s)]
['abca', 'bcab', 'cbac']

该解决方案使用负前瞻断言,这意味着“仅当当前位置后面没有匹配其他内容时才匹配当前位置。”现在,看看前瞻断言 - (?!\1)。这意味着“仅当当前字符后面没有第一个字符时才匹配当前字符。”

【讨论】:

  • 你应该解释一下这是做什么的,因为不是每个人都知道正则表达式环视语义。
  • spinlok:您似乎在断言第一组与 \1 不匹配,这似乎是不可能的:(.)(?<!\1)。我相信您的意思是使用否定的 look-ahead 断言(?!),无论如何这更有效。
  • 事实上,反向引用在lookbehinds中是非法的。你真的测试过这个吗?但是@bukzor 是对的,如果您将后视更改为前瞻,它就可以工作。
  • 不是特别的,但是正则表达式引擎必须将反向引用视为可变长度的结构,这意味着它们不能用于lookbehinds(当然,.NET 和 JGSoft 除外)。 Python 应该 在编译正则表达式时将其标记为错误;正如here所讨论的那样,它不是一个错误。
  • 顺便说一句,那些后视不应该像这样点之后出现吗? @ 987654326@ 以您的方式,第一个后视似乎断言捕获组与它刚刚匹配的组并不真正匹配。 ;) 无论如何,我已经在几个基于 Python 的在线正则表达式测试器中尝试了您的正则表达式,但它在其中任何一个中都不起作用。
【解决方案2】:

有很多方法可以做到这一点。这可能是最简单的:

re.findall(r'''
           \b          #The beginning of a word (a word boundary)
           ([a-z])     #One letter
           (?!\w*\1\B) #The rest of this word may not contain the starting letter except at the end of the word
           [a-z]*      #Any number of other letters
           \1          #The starting letter we captured in step 2
           \b          #The end of the word (another word boundary)
           ''', l, re.IGNORECASE | re.VERBOSE)

如果您愿意,可以通过将[a-z] 替换为\w 来稍微放宽要求。这将允许数字和下划线以及字母。您还可以通过将模式中的最后一个 * 更改为 {2} 来将其限制为 4 个字符的单词。

另外请注意,我对 Python 不是很熟悉,所以我假设您对 findall 的使用是正确的。

【讨论】:

  • -1 OP 已经尝试过类似的方法,但发现它不够;您错过了中间字母与开头/结尾匹配的要求。
  • @KarlKnechtel - 你说得对,我确实错过了那部分。我的错。我已经编辑了模式来解决这个问题。
  • 你可以通过展示 re.VERBOSE 标志来为他服务。这也会使你的答案更短。
  • @bukzor - 好电话。正如我所说,我对 Python 不太熟悉,所以如果我的语法有误,请告诉我。
【解决方案3】:

您需要使用正则表达式吗?这是一种更 Pythonic 的方式来做同样的事情:

l = """abca
bcab
aaba
cccc
cbac
babb
"""

for word in l.split():
  if word[-1] == word[0] and word[0] not in word[1:-1]:
     print word

【讨论】:

    【解决方案4】:

    我会这样做:

    result = re.findall(r"\b([a-z])(?:(?!\1)[a-z]){2}\1\b", subject)
    

    这与贾斯汀的回答类似,除了其中一个进行一次性前瞻,这个在每个字母被消耗时检查它。

    \b
    ([a-z])  # Capture the first letter.
    (?:
      (?!\1)   # Unless it's the same as the first letter...
      [a-z]    # ...consume another letter.
    ){2}
    \1
    \b
    

    我不知道你的真实数据是什么样子的,所以随意选择了[a-z],因为它适用于你的示例数据。出于同样的原因,我将长度限制为四个字符。与贾斯汀的回答一样,您可能希望将 {2} 更改为 *+ 或其他一些量词。

    【讨论】:

    • 这是一个有趣的转折。 +1。除了清晰/简洁之外,您还有什么更喜欢这个版本的原因?
    【解决方案5】:

    用正则表达式来解决问题。

    [
        word
        for word in words.split('\n')
        if word[0] == word[-1]
        and word[0] not in word[1:-1]
    ]
    

    【讨论】:

    • any() 有点矫枉过正。 word[0] in word[1:-1] 效果一样。
    • 呃,是的,让我解决这个问题,这很愚蠢。简单胜于复杂:)
    【解决方案6】:

    您可以使用否定的lookahead 或lookbehind 断言来做到这一点;详情请见http://docs.python.org/library/re.html

    【讨论】:

      【解决方案7】:

      不是 Python 大师,但也许是这个

      re.findall('^(.)(?:(?!\1).)*\1$', l, re.MULTILINE)
      

      扩展(使用多行修饰符):

      ^                # begin of line
        (.)            # capture grp 1, any char except newline
        (?:            # grouping
           (?!\1)         # Lookahead assertion, not what was in capture group 1 (backref to 1)
           .              # this is ok, grab any char except newline
        )*             # end grouping, do 0 or more times (could force length with {2} instead of *)
        \1             # backref to group 1, this character must be the same
      $                # end of line
      

      【讨论】:

        猜你喜欢
        • 2013-08-23
        • 1970-01-01
        • 2010-12-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-06-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多