使用 Regex python 以 `|` 分隔的标记错误

Error in tag separated by `|` using Regex python

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

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

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

您的问题是 '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)

您需要确保只替换 'REF',前提是它前面没有 'C''B''R'

请注意,这在某些情况下仍会导致问题,例如 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"|", string_data )
print(result)

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

由于您最重要的问题是正确拆分字符串,因此我只尝试解决这个问题。您可以在之后追加和添加 |

此模式似乎有效:

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

解释:

  1. (XYZ|CREF|BREF|RREF|REF): : 这很明显。您正在寻找标签的开头。顺序很重要。即把最短的子串REF放在最后。
  2. [a-zA-Z\s]+? :匹配标签后出现的任意字符和space,勉强。不情愿,因为如果引擎到达 CREF 的开始,我们希望它停在那里而不是接收更多字符 "greedily"。由于使用 "reluctance",第 (4) 点中的标签顺序很重要。
  3. (LLC)? : 这是一种所有已知单词的例外列表,这些单词以标签可能开头的字符序列结尾。 (为此,我想不出任何其他方法。)必须知道异常列表,并且可以单独配置并附加到模式运行时。如果事先知道输入数据结构并且此类异常是有限的和已知的,那么这不是瓶颈。否则,是的。
  4. (?=(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 )

您可以匹配一个可选的 BR 或匹配一个 C ,当前面没有 L 时使用负向后视。

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

说明

  • (?:非捕获组
    • [BR]? 匹配可选的 BR
    • |
    • (?<!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

重新导入

字符串="XYZ:MUMBAI UNIVERSITYCREF:PUNE UNIVERSITYBREF:DADAR UNIVERSITYRREF:KOLHAPUR UNIVERCITY LLCREF:SOLAPUR UNIVERSITY"

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

匹配 = re.finditer(regx,字符串)

标签=[]

对于比赛中的比赛: tag.append(match.group())

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