正则表达式从字符串中提取特定文本[重复]

Posted

技术标签:

【中文标题】正则表达式从字符串中提取特定文本[重复]【英文标题】:Regular Expression to extract specific text from string [duplicate] 【发布时间】:2019-08-15 07:32:46 【问题描述】:

我是 Regex 的新手,我尝试从字符串列表中提取 16 倍字符的文本。

示例列表:

myString = ['  pon-3-1    |    UnReg 5A594F4380661123           1234567890               Active',
            '  pon-3-1    |    UnReg 5A594F43805FA456           1234567890               Active',
            '  pon-3-1    |    UnReg 4244434D73B24789           1234567890               Active', 
            '  pon-3-1    |    UnReg 5A594F43805FB000           1234567890               Active',
            'sw-frombananaramatoyourmama-01'
           ]

我不能使用像 (\w16) 这样的简单正则表达式,因为这将包含所有 16 个字符的文本。 我还尝试了 (\w+A) ,根据字符串中的字符,它不会返回正确的结果。

newArry = []
for i in myString:
   number = re.search('(\w16)', i)
   newArr.append(number[0])

print(newArr)

返回:

['5A594F4380661123', '5A594F43805FA456', '4244434D73B24789', '5A594F43805FB000', 'frombananaramato']
    我只想提取: 5A594F4380661123 5A594F43805FA456 4244434D73B24789 5A594F43805FB000

有什么想法吗?

在此先感谢

【问题讨论】:

那么,you 如何将那些特定的 16 字符子字符串与其他子字符串区分开来?例如,如果它们总是大写,请使用该事实。您还可以查看单词边界,正则表达式支持。 ...通缉的似乎也被封闭在空格中... re.findall(r'UnReg\s(.16)', ' '.join(myString)) @jonrsharpe 是的,没错。总是大写。不过请注意,我是 Regex 的新手,还不知道如何将数字与字母和大写字母结合起来。 然后参见例如***.com/questions/4736/learning-regular-expressions 【参考方案1】:

如果您想确保 16 个字符被非字母包围,请尝试

re.search(r'\b([0-9A-F]16)\b', i)

\b“单词边界”运算符匹配一个位置,该位置一侧被字母包围,另一侧被非字母包围。

(如果您想更具体地确定哪些非字母,您可以使用环视:

re.search(r'(?<![0-9A-F])([0-9A-F]16)(?![0-9A-F])', i)

(?&lt;!...) 表示 “前面不能有 ...”(?!...) 表示 “后面不能有 ...”。)

您还会注意到,我将字符类收紧为仅匹配十六进制数字,这本身已经足以解决您的示例问题,并为正则表达式使用了 r'...' 原始字符串,您可能应该总是这样做(至少在你完全理解 Python 非原始字符串中的反斜杠是如何被破坏之前)。

【讨论】:

哇!这是令人印象深刻的感谢。两种解决方案都可以完美运行。我还测试了@בנימין כהן sn-p,它运行良好。如果要比较他和您的第一个 sn-p,我假设您的 sn-ps 提供了对字符串的更严格和准确的搜索?还是它们只是实现相同结果的 2 倍不同的方式。 另一个答案不限制匹配的上下文,所以它仍然会选择前 16 个例如20 个字符的字符串。使用边界标记,您不会匹配较长的十六进制字符串的子字符串。【参考方案2】:

使用正则表达式集

number = re.search("([\dABCDEF]16)", i)

这将搜索任何长度为 16 的字符串,其中包含任何数字 (\d)、'A'、'B'、'C'、'D'、'E' 或 'F'

【讨论】:

【参考方案3】:

你可以试试这个,假设十六进制代码总是以UnReg开头

re.findall(r'UnReg\s+([\dA-F]16)',';'.join(myString))

【讨论】:

谢谢。似乎工作得很好。由于正则表达式所在的现有函数结构,我更喜欢 re.search 方法。但是,如果我不正确,我将使用这个 sn-p。【参考方案4】:

使用re.findall 避免for循环。我会在模式中指定UnReg(如果您的真实数据中有一个),这样正则表达式就不会包含其他 16 个字符的文本。

>>> import re
>>> newArr = re.findall(r'UnReg\s(.16)', ' '.join(myString))
>>> print(newArr)
['5A594F4380661123', '5A594F43805FA456', '4244434D73B24789', '5A594F43805FB000']

【讨论】:

啊,我明白你的意思了。说得通。好的,让我测试一下并回复你。 @StephanDuToit btw 有用吗? 抱歉回复晚了。是的,它在一定程度上做到了。一旦我开始使用非常大的列表,我就会发现一些小问题,比如某些类型的数字匹配不正确。但这仅仅是因为您的代码是基于我提供的信息。我应该提供更多细节。无论如何,我最终使用了@triplee 代码的略微修改版本: (? 【参考方案5】:

在你的正则表达式中更具体:告诉它你知道什么!

如果您明显意识到实际结果与预期结果在某些特定方面有所不同,请尝试从中获得优势。

\w 匹配字母 ([A-Za-z])、数字 ([0-9]) 和 _,您似乎正在搜索 16 位十六进制数字。构建一个特定的character class。

另一个观察结果是您希望将 16 位十六进制数字块括在空格中,这可以通过捕获部分周围的字符正则表达式 befor(capt)after 或添加 anchors/boundaries 来表示。

【讨论】:

注意,谢谢!我收到了一些建议的解决方案。去测试每一个,然后研究它背后的方法。 @StephanDuToit 还考虑了描述上下文的非捕获部分。祝你好运:)

以上是关于正则表达式从字符串中提取特定文本[重复]的主要内容,如果未能解决你的问题,请参考以下文章

构建正则表达式(RegEx)以提取 HTML 标记的文本 [重复]

[使用正则表达式从python文本中提取特定单词

正则表达式从字符串中提取 IP 地址 [重复]

在 Python 中使用正则表达式从特定 xml 标记中提取特定值 [重复]

正则表达式

正则表达式