【问题标题】:Find how many words are in a sentence that meet specific conditions找出一个句子中有多少个单词满足特定条件
【发布时间】:2021-10-18 22:28:02
【问题描述】:

有一个招聘任务,我想用正则表达式来解决。

一个句子是由一组单词组成的。每个单词由字母[a-zA-Z] 组成,其中可能包含一个或多个破折号,并且可能以句点 (.)、逗号 (,)、问号 (?) 或感叹号 (!) 等标点符号结尾。每个单词不能以任何非字母或数字开头。也接受由空格字符分隔的单个字母。

破折号将两个或多个单词合二为一并且应该被接受(但双破折号“--”和更多不被接受),而单词末尾的其他有效标点符号应该被删除。

有效词(例子):

  • "foo-foo?!.,": result = "foo-foo",
  • "f-foo-foo?!.,": 结果 = "f-foo-foo",

无效词(示例):

  • "!@foo-foo{{}}}(("
  • “foo--foo”
  • “f-foo@-@foo”
  • “f123-foo123-foo-”
  • “-f-foo-foo-”

我尝试只用正则表达式解决python中的问题:

import re

TESTSTR1 = 'there should be 9 valid  words, including: a well-behave, right?'
TESTSTR2 = 'blabla! bla121 {{blabla123bla.. bla-blablabla!! b;a-bla@!. blabla bla-bla-bla-bla **bla-bla'
TESTSTR3 = '{{)foo! ~~foo121 foo--foo?. foo-foo?!{. @foo-foo! f 23 foo2 f-ff-fff-ffff!.,?  **foo-f'

TESTSTR1_EXPECTED = ['there', 'should', 'be', 'valid', 'words', 'including', 'a', 'well-behave','right']
TESTSTR2_EXPECTED = ['blabla', 'bla-blablabla', 'blabla', 'bla-bla-bla-bla', 'bla-bla']
TESTSTR3_EXPECTED = ['f', 'f-ff-fff-ffff','foo-f']


def find_words(sentence: str) -> list:
    pattern_dash = r'\b([^\d\s]+(?:-\w+[a-zA-Z]*))\b'
    pattern = r'\b(?!\w+-\w+)(?!-\w+)[a-zA-Z]+\b'

    words = re.findall(pattern_dash, sentence)
    words += re.findall(pattern, sentence)

    return words


if __name__ == "__main__":
    print('====================== TEST1 ======================')
    print(f'Expected "TESTSTR1" = {TESTSTR1_EXPECTED}')
    print(f'Result "TESTSTR1"   = {find_words(TESTSTR1)}')
        
    print('====================== TEST2 ======================')
    print(f'Expected "TESTSTR2" = {TESTSTR2_EXPECTED}')
    print(f'Result "TESTSTR2"   = {find_words(TESTSTR2)}')

    print('====================== TEST3 ======================')
    print(f'Expected "TESTSTR3" = {TESTSTR3_EXPECTED}')
    print(f'Result "TESTSTR3"   = {find_words(TESTSTR3)}')

首先我想找到所有包含破折号(“pattern_dash”)的有效词,然后是所有其他有效词(不包括那些已经找到的)。

我尝试了许多不同的正则表达式组合,但都没有成功。我不确定该任务是否可以仅使用正则表达式来解决。

有谁知道是否可以仅使用正则表达式来解决它?你知道怎么做吗?

非常感谢

【问题讨论】:

    标签: python regex


    【解决方案1】:

    要获取示例数据中的匹配项,您可以使用捕获组。

    首先匹配空格或*,然后捕获仅包含A-Za-z 的单词,可选地以- 分隔,并断言单词以空格、字符串结尾或结尾1 个或多个标点字符,后跟右侧空白边界。

    (?:[ *]|^)([a-zA-Z]+(?:-[a-zA-Z]+)*)(?= |$|[.,!?:]+(?!\S))
    

    模式匹配的部分:

    • (?:[ *]|^) 非捕获组,匹配 * 或断言字符串的开头
    • ( 捕获第 1 组
      • [a-zA-Z]+ 匹配 1+ 次出现的 A-Za-z
      • (?:-[a-zA-Z]+)* 可以选择在前面加上 - 重复相同的内容
    • )关闭第一组
    • (?= 正向前瞻,断言直接向右是
      • 匹配一个空格
      • |或者
      • $断言字符串结束
      • |或者
      • [.,!?:]+(?!\S) 从字符类 [.,!?:] 中匹配 1 个或多个匹配项,并在右侧声明一个空白边界
    • ) 关闭前瞻

    查看regex demoPython demo

    例如

    import re
    
    strings = [
         "there should be 9 valid  words, including: a well-behave, right?",
         "blabla! bla121 {{blabla123bla.. bla-blablabla!! b;a-bla@!. blabla bla-bla-bla-bla **bla-bla",
         "{{)foo! ~~foo121 foo--foo?. foo-foo?!{. @foo-foo! f 23 foo2 f-ff-fff-ffff!.,?  **foo-f"
    ]
    
    pattern = r"(?:[ *]|^)([a-zA-Z]+(?:-[a-zA-Z]+)*)(?= |$|[.,!?:]+(?!\S))"
    for s in strings:
         print(re.findall(pattern, s, re.M))
    

    输出

    ['there', 'should', 'be', 'valid', 'words', 'including', 'a', 'well-behave', 'right']
    ['blabla', 'bla-blablabla', 'blabla', 'bla-bla-bla-bla', 'bla-bla']
    ['f', 'f-ff-fff-ffff', 'foo-f']
    

    【讨论】:

      猜你喜欢
      • 2017-05-12
      • 2012-12-04
      • 2021-12-23
      • 1970-01-01
      • 2020-10-23
      • 1970-01-01
      • 2012-01-22
      • 2012-04-22
      • 2011-05-12
      相关资源
      最近更新 更多