有一个招聘任务,我想只用正则表达式来解决。
一个句子是由一组单词组成的。每个单词由字母[a-zA-Z]
组成,可以包含一个或多个破折号,并以句号(.)、逗号(,)、问号(?)或感叹号(!)等标点符号结尾。每个单词不能以非字母或数字开头。以空格分隔的单个字母也可以。
破折号将两个或多个单词连接成一个单词,应该被接受(但双破折号"——")而更多的不是),而其他有效的标点符号,在单词的末尾,应该被删除。
有效词(示例):
- "foo ? !,":结果="foo-foo",
- "f-foo-foo ? !,":结果="f-foo-foo",
无效字(示例):
- "! @foo-foo{{}}}(">
- "foo - foo"
- "f-foo@ -@foo"
- "f123-foo123-foo产生绯闻。
- "-f-foo-foo产生绯闻。
我试图在python中仅使用regex解决问题:
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([^ds]+(?:-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")的有效单词,然后是所有其他有效单词(不包括那些已经找到的)。
我尝试了许多不同的正则表达式组合,但没有成功。我不确定该任务是否仅使用正则表达式即可解决。
是否有人知道它是可能的解决它只使用正则表达式?你知道怎么做吗?
多谢
要获得示例数据中的匹配项,可以使用捕获组。
首先匹配空格或*
,然后仅用a- za -z捕获单词,可选地用-
分隔,并断言单词以空格、字符串的结尾或1个或多个标点符号结束,这些标点符号后跟一个右侧空白边界。
(?:[ *]|^)([a-zA-Z]+(?:-[a-zA-Z]+)*)(?= |$|[.,!?:]+(?!S))
部分模式匹配:
(?:[ *]|^)
非捕获组,匹配或
*
或断言字符串 的开头(
Capturegroup 1[a-zA-Z]+
A-Za-z匹配1+次(?:-[a-zA-Z]+)*
可选地在-
之前重复相同的内容
)
关闭组1(?=
正向前看,断言直接向右是匹配空格
|
或$
断言字符串的结束|
或[.,!?:]+(?!S)
从字符类[.,!?:]
中匹配1个或多个字符,并在右侧断言一个空白边界
)
Close forward
查看正则表达式演示和Python演示
例如
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']