使用正则表达式 python 由 `|` 分隔的标签中的错误

Posted

技术标签:

【中文标题】使用正则表达式 python 由 `|` 分隔的标签中的错误【英文标题】:Error in tag separated by `|` using Regex python 【发布时间】:2020-06-08 21:17:42 【问题描述】:

我想在每个标签之前添加|。 请检查我使用的以下代码。

tags = ['XYZ', 'CREF', 'BREF', 'RREF', 'REF']

string_data = 'XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY'

for each_tag in tags:
    result = string_data.replace(each_tag, "|" + each_tag)
    print(result)

我怎样才能使用正则表达式?

输入字符串:

XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY

实际结果(错误):

XYZ:MUMBAI UNIVERSITYC|REF:PUNE UNIVERSITYB|REF:DADAR UNIVERSITYR|REF:KOLHAPUR UNIVERCITY LLC|REF:SOLAPUR UNIVERSITY

预期结果:

|XYZ:MUMBAI UNIVERSITY|CREF:PUNE UNIVERSITY|BREF:DADAR UNIVERSITY|RREF:KOLHAPUR UNIVERCITY LLC|REF:SOLAPUR UNIVERSITY

有什么方法可以使用正则表达式吗?

【问题讨论】:

很遗憾,我们无法知道“LLCREF:”应该是“LLC/REF:”还是“LL/CREF:”。 不需要正则表达式。使用这样的东西:"|" + "|".join(['XYZ', 'CREF', 'BREF', 'RREF']) 你的错误结果和预期的输出看起来一样,对吧? @GaganTK 否,请检查上述错误结果和预期结果。 @AkshayGodase 好的,知道了。您能否将您尝试过的代码添加到问题中? 【参考方案1】:

重新导入

string = "XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERSITY LLCREF:SOLAPUR UNIVERSITY"

regx = "(XYZ|[C|B|R]REF|REF):[a-zA-Z\s]+?(LLC)?(?=(XYZ|[C|B|R]REF )|REF|$)"

matches = re.finditer(regx, string)

标签 = []

匹配中的匹配: tag.append(match.group())

结果=“|” + "|".join(标签) 打印(结果)

【讨论】:

欢迎来到 ***,并祝贺您的​​第一篇文章。如果您将代码格式化为代码,并添加一些文本来描述您的答案为何/如何起作用,您将获得更积极的回应(即支持和提高声誉)。【参考方案2】:

您可以匹配可选的BR,或者在前面没有L 的情况下匹配C,使用否定后向查找。

(?:[BR]?|(?<!L)C)REF|^(?!\|)

说明

(?:非捕获组 [BR]? 匹配可选的 BR |或者 (?&lt;!L)C 匹配 C 并断言左边的不是 L )关闭群 REF 字面匹配 |或者 ^(?!\|) 断言字符串的开头不是直接跟在 | 之后,以防止在已经存在的情况下以双 || 开头

Regex demo | Python demo

在替换中使用以管道开头的匹配

|\g<0>

例如

import re

regex = r"(?:[BR]?|(?<!L)C)REF|^(?!\|)"
test_str = "XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY"
subst = "|\\g<0>"
result = re.sub(regex, subst, test_str)

print (result)

输出

|XYZ:MUMBAI UNIVERSITY|CREF:PUNE UNIVERSITY|BREF:DADAR UNIVERSITY|RREF:KOLHAPUR UNIVERCITY LLC|REF:SOLAPUR UNIVERSITY

【讨论】:

@The_fourth_bird 它工作成功。如果我在另一个字符串上测试过它,比如"XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLBREF:SOLAPUR UNIVERSITY",那么它就不起作用了。这适用于任何情况意味着如果在 REF 之前如果我在 A-Z 中有任何后者,那么我会工作。 @The_fourth_bird 请检查上面的注释突出显示的字符串。如果您有任何问题,请告诉我。 您可以在后视中使用字符类 A-Z。 regex101.com/r/KtfLAR/1 但它与 LLLREF 不匹配。这种情况下的预期是什么?你能更新 regex101 链接什么应该和什么不应该匹配?【参考方案3】:

由于您最重要的问题是正确拆分字符串,因此我仅尝试解决此问题。您可以在之后附加和前置 |

这种模式似乎奏效了:

(XYZ|CREF|BREF|RREF|REF):[a-zA-Z\\s]+?(LLC)?(?=(XYZ|CREF|BREF|RREF|REF)|$)

解释:

    (XYZ|CREF|BREF|RREF|REF): 这很明显。您正在寻找标签的开头。顺序很重要。也就是把最短的子串REF放在最后。 [a-zA-Z\\s]+? 匹配标记后出现的任何字符和空格,不情愿地。不情愿,因为如果引擎到达CREF 的开头,我们希望它停在那里而不是“贪婪地”获取更多字符。由于使用了“不情愿”,第 (4) 点中的标签顺序很重要。 (LLC)? : 这是一种以标签开头的字符序列结尾的所有已知单词的例外列表。 (为此,我想不出任何其他方式。)必须知道异常列表,并且可以单独配置并附加到模式运行时。如果事先知道输入数据结构并且此类异常是有限且已知的,则这不是瓶颈。否则,是的。 (?=(XYZ|CREF|BREF|RREF|REF)|$) : 确保引擎在发现其中一个标签出现时停止。 $ 允许在输入结束时停止,如果没有更多标签。

这将为您提供的输入字符串提供以下输出:

XYZ:MUMBAI UNIVERSITY
CREF:PUNE UNIVERSITY
BREF:DADAR UNIVERSITY
RREF:KOLHAPUR UNIVERCITY LLC
REF:SOLAPUR UNIVERSITY

编辑

添加我测试过的 Python 3.8.1 代码:

import re

s = "XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY"

p = "(XYZ|CREF|BREF|RREF|REF):[a-zA-Z\\s]+?(LLC)?(?=(XYZ|CREF|BREF|RREF|REF)|$)"

matches = re.finditer( p,s )

tag_list = [ m.group() for m in matches ]
s2 = "|" + "|".join( tag_list )
print( s2 )

【讨论】:

@Sree_Kumar 尝试了上面的代码,但没有得到结果。 @AkshayGodase 我已经发布了我用来测试的代码。你能查一下吗? @Sreee_Kumar 我已经测试了你的代码,它可以正常工作。但我期待预期的结果。请检查以下|XYZ:MUMBAI UNIVERSITY|CREF:PUNE UNIVERSITY|BREF:DADAR UNIVERSITY|RREF:KOLHAPUR UNIVERCITY LLC|REF:SOLAPUR UNIVERSITY 我不想在结果上方分离我需要的所有组 好的。在这之后简单地加入零件还不够吗?或者你想要一个正则表达式级别替换的解决方案?【参考方案4】:

您的问题是 'CREF''BREF''RREF''REF' 之间的重复 - 因为 'REF' 在所有其他三个中,如果您将代码修复为此,您最终会得到重复的替换:

tags = ['XYZ', 'CREF', 'BREF', 'RREF', 'REF']

string_data = 'XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY'

for each_tag in tags:
    string_data= string_data.replace(each_tag, "|" + each_tag)
    print(string_data)

您需要确保仅在 'C''B''R' 之前没有替换 'REF'

请注意,对于 XYZ:CARE BEARREF 等某些情况,这仍然会导致问题。 IE。你可能会期待|XYZ:CARE BEAR|REF,但你会得到|XYZ:CARE BEA|RREF。如果您想避免这种情况,您需要更准确地了解实际规则。

如果您知道不会发生此类问题,这可行:

import re

string_data = 'XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY'

result = re.sub("(XYZ|CREF|BREF|RREF|REF)", r"|\1", string_data )
print(result)

这避免了特定的检查,因为正则表达式会考虑排序,并且在文本已作为先前值的一部分匹配后不会匹配 REF。

【讨论】:

我尝试了您的代码,但我的预期结果与您的结果不匹配。

以上是关于使用正则表达式 python 由 `|` 分隔的标签中的错误的主要内容,如果未能解决你的问题,请参考以下文章

Python 正则表达式将空格分隔的单词分隔成一个列表

如何构建一个正则表达式来捕获由单个空格分隔的单词?

用于匹配由“$”字符分隔的正非零双精度字符串的正则表达式

Python 中的正则表达式 findall()

《python核心编程》——正则表达式学习笔记(课后练习)

Python爬虫编程思想(35):用正则表达式搜索替换和分隔字符串