为复杂的正则表达式添加例外

时间:2019-03-15 15:26:37

标签: python regex

有一个非常复杂的正则表达式。

但是我对此有疑问。如果#++后面有字母,则会将其删除。

问题:如何为(C ++和C#令牌)当前的正则表达式添加例外?

我使用了下一个正则表达式:

import re

text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'
text = re.sub(r'[!,.:;—](?= |$)', ' ', text)
print(re.sub(r'(?i)(?:(?!\.net\b|\b-\b)[^\w\s])+(?=[^\w\s]*\b)', ' ', text))

我得到了下一个结果:

'Must-have skills   .Net programming experience   2 years experience in C++  C .Net  C .Net  C .Net '

所需结果:

'Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C .Net '

当前正则表达式详细信息

  • (?i)-启用不区分大小写的模式
  • (?:(?!\.net\b|\b-\b)[^\w\s])+-任何不出现任何序列的标点符号([^\w\s]),如果出现1个或更多,则越多越好。
    • \.net\b-.net整个词
    • |-或
    • \b-\b-用字符char括起来的连字符
  • (?=[^\w\s]*\b)-一个正向的超前查询,需要0+个标点符号,其后紧接当前位置的右侧是单词边界位置。

3 个答案:

答案 0 :(得分:3)

它与您的输出并不完全相同,但是我可以通过反转两个re.sub的顺序并在其后添加负数来实现空白而仅使用空白。

text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'
text = re.sub(r'(?i)(?:(?!\.net\b|\b-\b)(?<!C)(?<!C\+)[^\w\s])+(?=[^\w\s]*\b)', ' ', text)
text = re.sub('[!,.:;—](?= |$)', ' ', text)

输出:

print(text)
Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C  .Net 

答案 1 :(得分:3)

修改

#1

与以下内容相同,但更短,我将一组字符定义为必须在捕获的字符之前

>>> import re

>>> text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'

>>> re.sub('(?:(?<!\S)|(?<=[\s\+\.C#]))[\-!,.:;—/]|[\-!,.:;—/](?=\s|$)', ' ', text)


#Output
'Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C  .Net '

说明

  • 这里的答案实际上与下面的答案相同,但是我没有声明必须对捕获的集合进行逐一作用的字符,而是将它们全部定义为一个集合。

#2

种类繁多的解决方案,但

稍后将发布说明;甚至可以对其进行改进以提高可读性

>>> import re

>>> text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'

>>> re.sub('(?:(?<!\S)|(?<=\s)|(?<=\+)|(?<=\.)|(?<=C)|(?<=#))[\-!,.:;—/]|[\-!,.:;—/](?=\s|$)', ' ', text)


#Output
'Must-have skills   .Net programming experience   2 years experience in C++  C# .Net  C++ .Net  C  .Net '

编辑:说明

  • 因此,通过以(?:打开,我要说的是,在这种情况下,我要捕获的查询应该在捕获集之前,该捕获集包含紧随(?:之后定义的内容。
  • 这里的关键是不能将以(?<!(?<=开头的前瞻设置为忽略一定范围的值,因此我必须先从(?:开始,然后再给出多个{ {1}}和(?<!表示捕获的内容该字符之前或之后,该其他字符之前,等等。
  • 因此,用(?<=打开后,我现在可以设置要捕获的值应该或不应该以
  • 开头的值
  • (?:开始确实是不需要的,但我将其包括在内是因为它可以产生安全网。它基本上说,如果范围(?<!\S) 如果前面带有任何随机的非空白字符,则不应捕获/作用范围
  • 对于[\-!,.:;—/],我是说* OR |(?<=\s)如果前面带有任何单个空格字符,则应捕获/执行*
  • 使用[\-!,.:;—/]的意思是,如果|(?<=\+)|(?<=\.)|(?<=C)以+ 、.或C开头,则应该捕获或执行,所以{{1}如果[\-!,.:;—/]中的}像字符串中的\. OR just . [a period]前面那样被捕获/作用(请记住[\-!,.:;—/]);如果C中的(?<=C)前面有;(请记住[\-!,.:;—/]),则会被捕获/执行。
  • +之前的最后一个(?<=\+)关闭)
  • |,因为您知道是OR,而且由于我无法将语句全部合为一体,因此我必须重新定义(?:,然后先说,捕获/执行|上的空格或字符串末尾。通过先行,您可以定义常规的单个字符串类型'ranges',这样您就可以实际使用[\-!,.:;—/]它们,但是当您使用先行记录时就不能这样做

答案 2 :(得分:2)

您可以使用单个替换项,方法是在一个组中捕获要保留的内容,并使用alternation删除不需要的内容。

这样,您可以使用要保留或要删除的案例扩展模式。在替换中,您使用捕获组。除了使用内联修饰符(?i),您还可以在代码中使用re.IGNORECASE

(c(?:\+{2}|#)|\.net\b)|[!,.:;/—]|-(?=[\d.])

这将匹配:

  • (捕获组
    • c(?:\+{2}|#)|\.net\b匹配c ++或c#或.net
  • )关闭捕获组
  • |
  • [!,.:;/—]匹配字符类中列出的任何字符
  • |
  • -(?=[\d.])匹配一个连字符,以断言直接在右边的是数字或点

Regex demo | Python demo

例如

import re
regex = r"(c(?:\+{2}|#)|\.net\b)|[!,.:;/—]|-(?=[\d.])"
text = 'Must-have skills: -.Net programming experience; -2 years experience in C++; C#/.Net, C++/.Net, C./.Net.'
text = re.sub(regex, r"\1 ", text, 0, re.IGNORECASE)

if text:
    print (text)

# Must-have skills   .Net  programming experience   2 years experience in C++   C#  .Net   C++  .Net   C  .Net