如果两个字符串之间存在子字符串,则提取两个字符串之间的文本

lmvvr0a8  于 2021-05-16  发布在  Spark
关注(0)|答案(2)|浏览(492)

我在一个名为“message”的列中有一个原始文本,如下所示:
示例dataframe

Date               message
2020-11-01         ['some not required text1', 'Startstring , 
                   'some not required text2', MandatorySubstring , 'some not 
                    required text3', 'ID :AB_CD, 'Stopstring' 'some not 
                    required text4', 'Startstring ID :cd_ab', 'some not 
                    required text5', 'ID :ghed','some not required text6', ID :zyx', 'Stopstring 'some 
                    not required text7']
2020-11-02         ['some not required text8', Startstring 'ID :ABCD', 
                   'some not required text9', 'ID :ED_GH', 'some not 
                    required text10', ID :X_YZ, Stopstring 'some not 
                    required text11', 'Startstring 
                    'some not required text12',MandatorySubstring 
                    'some not required text13', ID :z_yx', 'some not required text14''Stopstring 
                    'some not required text15']

如果在startstring和stopstring之间存在mandatorysubstring,我希望提取id:in之后的字符串;如果在startstring和stopstring之间不存在mandatorysubstring,则丢弃id。在一个日期中可能有多个这样的示例。
预期产量:

Date               message
2020-11-01         AB_CD 
2020-11-02         z_yx

我尝试了以下模式:

pattern = StartString\s*((?:(?!StartString).)*?MandatoryString 1.*?)\s*Stopstring

它给出了startstring和stoptstring之间的所有文本。我现在不知道如何从这个文本中提取id:之后的文本。
有人能为我提供这个场景的regex模式吗?非常感谢您在这方面的帮助。谢谢

zvms9eto

zvms9eto1#

考虑到当前的输入,我建议

Startstring(?:(?!Startstring).)*?MandatorySubstring(?:(?!Startstring).)*?,['\s]*ID\s*:\s*([^',]*).*?Stopstring

查看regex演示。细节:
Startstring-左侧分隔符
(?:(?!Startstring)。)*?-任何零个或多个字符,每个字符都不启动“Startstring”字符序列
MandatorySubstring—必须出现在左右分隔符之间的字符串
(?:(?!Startstring)。)*?-任何零个或多个字符,每个字符都不启动“Startstring”字符序列
-逗号
['\s]*-零个或多个或空白 `ID`-字符串 `\s*:\s*`-冒号,用零个或多个空格括起来 `([^',]*)`-group1:除'以外的任何零个或多个字符
.*?-除换行符以外的任何零个或多个字符,尽可能少
Stopstring-右分隔符。

azpvetkf

azpvetkf2#

我们可以分三个阶段来做。首先,使用regex在这些字符串中搜索开始字符串、强制子字符串和停止字符串。我们使用否定的先行Assert来确保强制子字符串确实位于两个相邻的开始字符串和停止字符串之间。一旦我们有了这些匹配项,我们就提取每个匹配项中存在的id,最后将它们压缩成一个列表。

def extract_ids(s):
    matches = re.findall(r'Startstring((?:(?!Startstring).)*)MandatorySubstring((?:(?!Stopstring).)*)Stopstring', s)
    all_ids = [re.findall(r'ID\s*:([^,]*)', group) for match in matches for group in match]
    ids_flat = [i for l in all_ids for i in l]
    return ids_flat

s1 = """['some not required text1', 'Startstring , 'some not required text2', MandatorySubstring , 'some not required text3', 'ID :AB_CD, 'Stopstring' 'some not required text4', 'Startstring ID :cd_ab', 'some not required text5', 'ID :ghed','some not required text6', ID :zyx', 'Stopstring 'some not required text7']"""

s2 = """['some not required text8', Startstring 'ID :ABCD', 'some not required text9', 'ID :ED_GH', 'some not required text10', ID :X_YZ, Stopstring 'some not required text11', 'Startstring 'some not required text12',MandatorySubstring 'some not required text13', ID :z_yx', 'some not required text14''Stopstring 'some not required text15']"""

>>> extract_ids(s1)
['AB_CD']

>>> extract_ids(s2)
["z_yx'"]

要将其应用于dataframe,只需使用'df['message'].map(extract\u id)`。

相关问题