解析并从字符串中提取信息

时间:2015-11-19 21:42:40

标签: python

我使用的是Windows操作系统,python 2.7 我列出了所有可用端口(COM1,3,4),当前输出为:

[('COM4', 'Neato Robotics USB Port (COM4)', 'USB VID:PID=2108:780C SNR=XXXX'), ('COM3', 'Intel(R) Active Management Technology - SOL (COM3)', 'PCI\\VEN_8086&DEV_9C3D&SUBSYS_05DE1028&REV_04\\3&11583659&0&B3'), ('COM1', 'Communications Port (COM1)', 'ACPI\\PNP0501\\0')]

我的问题是,我想使用/ connect to COM4。所以我希望我能找到一种方法来解析该端口并在之后使用它。即如何从那个长字符串中提取COM4?我计划通过PID来定位它。

感谢。

2 个答案:

答案 0 :(得分:2)

一点一滴:

HTTP

答案 1 :(得分:1)

假设您的字符串存储在value变量中:

value = "[('COM4', 'Neato Robotics USB Port (COM4)', 'USB VID:PID=2108:780C SNR=XXXX'), ('COM3', 'Intel(R) Active Management Technology - SOL (COM3)', 'PCI\\VEN_8086&DEV_9C3D&SUBSYS_05DE1028&REV_04\\3&11583659&0&B3'), ('COM1', 'Communications Port (COM1)', 'ACPI\\PNP0501\\0')]"
data = [tuple(item[1:][:-1].split("', '")) for item in value[2:][:-2].split('), (')]

假设:

data = [('COM4', 'Neato Robotics USB Port (COM4)', 'USB VID:PID=2108:780C SNR=XXXX'), ('COM3', 'Intel(R) Active Management Technology - SOL (COM3)', 'PCI\\VEN_8086&DEV_9C3D&SUBSYS_05DE1028&REV_04\\3&11583659&0&B3'), ('COM1', 'Communications Port (COM1)', 'ACPI\\PNP0501\\0')]

然后可以使用正则表达式提取PID值:

import re
pid = re.search('VID:PID=.*:(.*) ', data[0][2]).group(1)

如果你想要VID和PID:

import re
match = re.search('VID:PID=(.*):(.*) ', data[0][2])
if match and len(match.groups()) > 0:
    vid = match  and match.group(1) or None
    pid = match and match.group(2) or None

更新

将端口映射到PID,反之亦然:

import re

data = [('COM4', 'Neato Robotics USB Port (COM4)', 'USB VID:PID=2108:780C SNR=XXXX'), ('COM3', 'Intel(R) Active Management Technology - SOL (COM3)', 'PCI\\VEN_8086&DEV_9C3D&SUBSYS_05DE1028&REV_04\\3&11583659&0&B3'), ('COM1', 'Communications Port (COM1)', 'ACPI\\PNP0501\\0')]

def extract_pid(dev_string):
    match = re.search('PID=.*:(.*) ', dev_string)
    groups = match and match.groups()
    return groups and len(groups) > 0 and groups[0] or None

port_to_pid_dict = dict((item[0], extract_pid(item[2])) for item in data)
# port_to_pid_dict = {'COM1': None, 'COM3': None, 'COM4': '2108'}
pid_to_port_dict = dict((extract_pid(item[2]), item[0]) for item in data if 'PID=' in item[2])
# pid_to_port_dict = {'2108': 'COM4'}

然后您可以使用pid_to_port_dict['2018'],即'COM4'

当然,如果您同时连接到计算机的同一产品的多个实例,则需要额外的逻辑:

import collections

pid_to_port_dict = collections.defaultdict(list)
for item in data:
    pid = extract_pid(item[2])
    if pid:
        pid_to_port_dict[pid].append(item[0])

现在pid_to_port_dict['2018']将通过一系列端口生成具有特定productId的产品连接到:['COM4']

检查产品ID和供应商ID可能是一个更好的主意,因为来自不同供应商的多个产品可以具有相同的产品ID。

更新2

我将如何做到这一点。点击here获取互动示例。

import collections
import re

class Device:
    def __init__(self, vendorId, productId, port):
        self.vendorId = vendorId
        self.productId = productId
        self.port = port

    def __repr__(self):
        return self.__str__()

    def __str__(self):
        return "Device {}:{} at {}".format(self.vendorId, self.productId, self.port)

def create_defaultdict_with_list():
    return collections.defaultdict(list)

class DeviceParser:
    def __init__(self, devices):
        self.devices = devices

    @staticmethod
    def _parse(device_string, port):
        match = re.search('VID:PID=(.*):(.*) ', device_string)
        if match and len(match.groups()) == 2:
            return Device(vendorId=match.group(1),
                          productId=match.group(2),
                          port=port)
        return None

    def parse_as_list(self):
        devices = []
        for port, description, dev_str in self.devices:
            dev = self._parse(dev_str, port)
            if dev:
                devices.append(dev)
        return devices

    def parse_as_vendor_map(self):
        vendors = collections.defaultdict(create_defaultdict_with_list)
        for port, description, dev_str in self.devices:
            dev = self._parse(dev_str, port)
            if not dev:
                continue
            vendors[dev.vendorId][dev.productId].append(dev)
        return vendors

def main():
    data = [
        ('COM4', 'Neato Robotics USB Port (COM4)', 'USB VID:PID=2108:780C SNR=XXXX'),
        ('COM3', 'Intel(R) Active Management Technology - SOL (COM3)', 'PCI\\VEN_8086&DEV_9C3D&SUBSYS_05DE1028&REV_04\\3&11583659&0&B3'),
        ('COM1', 'Communications Port (COM1)', 'ACPI\\PNP0501\\0')
    ]
    parser = DeviceParser(data)
    devices = parser.parse_as_list()
    print('recognized device list:', devices)
    vendors = parser.parse_as_vendor_map()
    print('device by vendorId and productId:', vendors['2108']['780C'])
    print('port of device:', vendors['2108']['780C'][0].port)

if __name__ == '__main__':
    main()