有一个非常复杂的正则表达式。
但是我对此有疑问。如果#
和++
后面有字母,则会将其删除。
问题:如何为(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+个标点符号,其后紧接当前位置的右侧是单词边界位置。答案 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.])
匹配一个连字符,以断言直接在右边的是数字或点例如
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