【问题标题】:Matching input string to similar dictionary keys Python将输入字符串匹配到类似的字典键Python
【发布时间】:2016-02-07 18:11:29
【问题描述】:

我有一本字典 output_dict,其中包含与文件签名及其相关扩展名有关的数据,即 '43 44 30 30 31': '.ISO'。我正在尝试编写一个脚本,该脚本将以字节为单位读取文件并返回字典中的任何匹配项。如果未找到匹配项,则返回最相似的值。

有没有办法让它逐个字节地读取文件,匹配直到它到达一个打破匹配的字节,返回之前匹配的键/值?

或者,我希望它能够匹配一定的数量,或者匹配非常相似的东西(2-3 字节差异)。如果没有匹配或没有类似的对象,我希望它打印一条消息。

目前,我的代码如下所示:

root_path = "testdir"
list_of_files = os.listdir(root_path)
for files in list_of_files:
    full_path = os.path.join(root_path, files)
    open_it = open(full_path, 'rb')
    read_it = open_it.read(x)
    convert_it = get_bytes_as_displayable_hex(read_it)
    convert_to_ascii = convert_it.encode('utf-8')
    convert_to_string = convert_to_ascii.decode(encoding='utf-8', errors="strict")
    result = (output_dict.get(convert_to_string))
    if result is not None:
        print("Scan complete, found: {} file(s)".format(result))
    else:
        result = difflib.get_close_matches(convert_to_string, output_dict, 2, 0.2)
        print(result)

因此,预期结果将类似于文件的前 4 个字节是 25 50 44 46。这些字节与字典交叉引用并将匹配它,结果返回“.PDF”。

如果前四个字节是 25 50 44 47,这不在字典中,但代码仍然会返回“.PDF”,因为它们非常相似。

感谢任何帮助以及任何建议,因为我对 Python 和一般编程非常陌生。

【问题讨论】:

  • “最相似的值”
  • 其中“最相似的值”是仅相差 2-3 个十六进制字节的键。即如果 FF D8 EE 00 不匹配,则返回 FF D9 EE 00 作为可能的结果。
  • 不太清楚要求的是什么。
  • 我不确定如何让它更清晰。我将编辑帖子以添加更多信息,看看是否有帮助。

标签: string python-3.x dictionary pattern-matching match


【解决方案1】:

发现这很有趣,所以编写了一个可能对你有用的代码 sn-p。假设每个字节都允许有一个小的差异。就像在您的评论中一样,如果控制值为FF D8 EE 00FF D9 EE 00 是可以接受的,那么FE D9 EF 01 也是可以接受的。在示例中,我将2 设置为可接受的范围,这意味着它将允许小于或大于控制值2 的值。

def create_list(value):
    # Convert a byte sequence (as string) into a list of int values.
    return [int(value[i:i + 2], 16) for i in range(0, len(value), 2)]


def check_if_close(value, control_value, accepted_range):
    print('Checking {} vs {}'.format(value, control_value))
    value = create_list(value)
    control_value = create_list(control_value)
    count = 0
    exact_match = 0
    for x in range(len(value)):
        if value[x] == control_value[x]:
            exact_match += 1
            continue
        for y in range(control_value[x] - accepted_range,
                       control_value[x] + accepted_range + 1):
            if y == value[x]:
                count += 1
                print('Unknown: {}, Predefined: {}'.format(y, control_value[x]))

    print('Exact matches:', exact_match)
    print('Bytes within range:', count)
    if exact_match + count == len(value):
        print('-- Within acceptable range\n')
    else:
        print('-- Not within acceptable range\n')

predefined = 'FFD8EE00'
unknown = 'FFD9EE00'
unknown2 = 'FED9EF01'
unknown3 = 'FFEFEE00'
check_if_close(unknown, predefined, 2)
check_if_close(unknown2, predefined, 2)
check_if_close(unknown3, predefined, 2)

predefined 将是您从 output_dict 获得的值,unknown 变量将您从文件中获得的十六进制值模拟为字符串。

您当然可以自己定义可接受的范围,以及可接受的匹配类型。此代码接受每个值对中的变体,但您可以轻松定义至少需要 4 个中的 3 个才能完全匹配。在示例中,unknownunknown2 在可接受范围内通过,而 unknown3 不在可接受范围内。

希望这能为您的程序提供一些想法。

【讨论】:

  • 这看起来很有希望,我会看看它,看看它是否有帮助。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2019-05-01
  • 2021-12-28
  • 1970-01-01
  • 2013-10-13
  • 1970-01-01
  • 1970-01-01
  • 2019-10-06
  • 2018-01-04
相关资源
最近更新 更多