regex 匹配十六进制部分的正则表达式

yizd12fk  于 2023-02-05  发布在  其他
关注(0)|答案(4)|浏览(200)

所以我需要使用regex来匹配十六进制字符串的一部分,但那部分是随机的。让我试着解释更多:
所以我有这个hexa数据:

70 75 62 71 00 7e 00 01 4c 00 06 72 61 6e 64 6f 6d 74 00 1c 4c 6a 2f 73 2f 6e 64 6f 6d 3b 78 70 77 25 00 00 00 20 f2 90 c2 91 c4 c4 ca 91 c0 c0 ca 91 94 cb c5 97 90 c5 90 c2 90 96 c7 ca 91 91 93 94 c6 c5 c6 cb c0 78

在这种情况下,我只需要匹配f2。但情况并不总是这样。每个数据都是不同的。唯一总是相同的是“00 00 00”部分和末尾的“78”。其余的都是随机的。
我设法做了下面的正则表达式:/(?=00 00 00).+?(?=78)/输出为:

00 00 00 20 f2 90 c2 91 c4 c4 ca 91 c0 c0 ca 91 94 cb c5 97 90 c5 90 c2 90 96 c7 ca 91 91 93 94 c6 c5 c6 cb c0

但是我不知道如何构建一个正则表达式来只取“f2”(提醒:并不总是f2)
有什么想法吗?

3phpmpom

3phpmpom1#

根据这篇评论中的解释,你需要的正则表达式是:

(?<=00 00 00 [0-9a-f]{2} )[0-9a-f]{2}

提供问题中的第一个输入字符串,这个正则表达式匹配f2(没有空格)。
检查一下online
工作原理:

(?<=                 # start of a positive lookbehind
  00 00 00           # match the exact string ("00 00 00 ")
  [0-9a-f]           # match one hex digit (lowercase only)
  {2}                # match the previous twice (i.e. two hex digits)
                     # there is a space after ")"
)                    # end of the lookbehind
[0-9a-f]{2}          # match two hex digits

正lookbehind的工作方式类似于非捕获组,但它不是匹配的一部分。基本上,它表示匹配部分([0-9a-f]{2})仅在其前面有lookbehind表达式的匹配时才匹配。
表达式的匹配部分是[0-9a-f]{2}(即两个十六进制数字)。
您需要添加i或任何使用regex引擎的标记,您使用它来表示"忽略大小写"(即regex的a-f部分也匹配A-F)。如果您不能(或不想)提供此标记,您可以将[0-9A-Fa-f]放在任何地方,它会工作。
如果您的正则表达式引擎不支持lookbehind,您可以使用捕获组获得相同的结果:

00 00 00 [0-9a-f]{2} ([0-9a-f]{2})

应用于同一个输入,这个正则表达式匹配00 00 00 20 f2,并且它的第一个(也是唯一的)捕获组匹配f2
检查它online

更新

如果输入字符串在匹配部分之后的某个地方包含78很重要,则将(?=(?: [0-9a-z]{2})* 78)添加到第一个正则表达式:

(?<=00 00 00 [0-9a-f]{2} )[0-9a-f]{2}(?=(?: [0-9a-z]{2})* 78)

(?=引入了一个正向前查找。它的行为类似于向后查找,但必须停留在reged的匹配部分之后,并根据位于字符串匹配部分之后的字符串部分进行验证。
(?:启动非捕获组。
在lookahead和lookbehind中,[0-9a-z]{2}后面或前面加一个空格可以确保整个匹配字符串只由2个用空格分隔的十六进制数字组成。您可以使用.*代替,但它将匹配任何内容,即使它们不遵循2个十六进制数字的格式。
对于没有lookaheads或lookbehinds的版本,请在正则表达式的末尾添加(?: [0-9a-z]{2})* 78

00 00 00 [0-9a-f]{2} ([0-9a-f]{2})(?: [0-9a-z]{2})* 78

正则表达式匹配以00 00 00开始并以78结束的整个字符串,第一个捕获组匹配00 00 00(您的目标)之后的第二个数字。

cld4siwp

cld4siwp2#

f2是否被星号包围?
无星号:

00 00 00 [a-f0-9]+ (?<hexits>[a-f0-9]+).+78

带星号:

\*(?<hexits>[a-f0-9]+)\*
rur96b6h

rur96b6h3#

您可以使用以下正则表达式匹配"00 00 00"后面的十六进制值:/00 00 00([0 - 9A-Fa-f] {2})/。所需的值位于捕获组中,由\1表示。
下面是一个演示:

import re

s = '70 75 62 71 00 7e 00 01 4c 00 06 72 61 6e 64 6f 6d 74 00 1c 4c 6a 2f 73 2f 6e 64 6f 6d 3b 78 70 77 25 00 00 00 20 f2 90 c2 91 c4 c4 ca 91 c0 c0 ca 91 94 cb c5 97 90 c5 90 c2 90 96 c7 ca 91 91 93 94 c6 c5 c6 cb c0 78'

match = re.search(r'00 00 00 ([0-9A-Fa-f]{2})', s)
if match:
    print(match.group(1))

输出将为:

f2
qxsslcnc

qxsslcnc4#

你并不需要正则表达式来完成这个过程,在一行中取3个字节的零的偏移量,然后取它后面的第4个字节:

s = '70 75 62 71 00 7e 00 01 4c 00 06 72 61 6e 64 6f 6d 74 00 1c 4c 6a 2f 73 2f 6e 64 6f 6d 3b 78 70 77 25 00 00 00 20 f2 90 c2 91 c4 c4 ca 91 c0 c0 ca 91 94 cb c5 97 90 c5 90 c2 90 96 c7 ca 91 91 93 94 c6 c5 c6 cb c0 78'
s2 = '01 02 03 00 00 00 05 06 07'

def locate(s):
    data = bytes.fromhex(s)
    offset = data.find(bytes([0,0,0]))
    return data[offset + 4]

print(f'{locate(s):02X}')
print(f'{locate(s2):02X}')

输出:

F2
06

您也可以直接从字符串中提取"f2"字符串:

offset = s.index('00 00 00')
print(s[offset + 12 : offset + 14]) # 'f2'

相关问题