首页 文章

如何用python解析oracle jdbc ezconnect

提问于
浏览
0

我试图搜索如何用python解析一个oracle jdbc字符串,它可以是不同的格式,但没有找到anythng .

问题:

输入字符串可以基于不同的模式:

  • jdbc:oracle:thin:@ // hostname.example.ru:1521/database.example.ru

  • jdbc:oracle:thin:@hostname:1521:DATABASE

我无法预测下次我会得到什么样的模式 . 所以我需要使用一些总是能够解析这样的字符串的包来不再实现一个自行车 .

更新_#0

仍未找到任何可以解析部件上的连接字符串而不实际连接到oracle的包 .

现在,我写了正则表达式来解析jdbc oracle ezconnect字符串,你可以用它来解析ezconnect:

^jdbc:oracle:thin:((?'username'[a-zA-Z0-9]{1,})([\/](?'password'[a-zA-Z0-9]{1,})){0,1}){0,1}@((\/\/){0,1}(?'hostname'[a-zA-Z0-9\.\-]*)(\:(?'port'\d+)){0,1})(\/(?'service_name'[a-zA-Z\.\-0-9]{1,}(\:(?'server_type'[a-zA-Z]{1,})){0,1}){0,1}(\/(?'instance_name'[a-zA-Z0-9]{1,})){0,1}){0,1}$

这是一个扩展的查询:

^
    jdbc:oracle:thin:
    (
        (?'username'[a-zA-Z0-9]{1,})
        ([\/]
            (?'password'[a-zA-Z0-9]{1,})
        ){0,1}
    ){0,1}
    @
    (
        (\/\/){0,1}
        (?'hostname'[a-zA-Z0-9\.\-]{1,})
        (\:(?'port'\d+)){0,1}
    )
    (\/
        (?'service_name'[a-zA-Z\.\-0-9]{1,}
            (\:
                (?'server_type'[a-zA-Z]{1,})
            ){0,1}
        ){0,1}
        (\/
            (?'instance_name'[a-zA-Z0-9]{1,})
        ){0,1}
    ){0,1}
$

你可以在这行测试它here

jdbc:oracle:thin:@//hostname.example.ru:1521/database.example.ru
jdbc:oracle:thin:@sales-server
jdbc:oracle:thin:@sales-server:3456
jdbc:oracle:thin:@sales-server/sales
jdbc:oracle:thin:@sales-server:80/sales
jdbc:oracle:thin:@sales-server/sales:dedicated/inst1
jdbc:oracle:thin:@sales-server//inst1
jdbc:oracle:thin:@sales-server:1521/sales.us.acme.com
jdbc:oracle:thin:@//sales-server/sales.us.acme.com
jdbc:oracle:thin:@//sales-server.us.acme.com/sales.us.oracle.com
jdbc:oracle:thin:wat@//sales-server.us.acme.com/sales.us.oracle.com
jdbc:oracle:thin:wat/wat@//sales-server.us.acme.com/sales.us.oracle.com
jdbc:oracle:thin:wat/wat@//sales-server.us.acme.com/sales.us.oracle.com:dedicated/instance
jdbc:oracle:thin:wat/wat@//sales-server.us.acme.com//instance
jdbc:oracle:thin:@non-ezconnect-string-test:1521:DATABASE

更新_#1

这段代码适用于python:

import re

jdbc_ezconnect = re.compile("^jdbc:oracle:thin:((?P<username>[a-zA-Z0-9]{1,})([\/](?P<password>[a-zA-Z0-9]{1,})){0,1}){0,1}@(?P<ezdb_name>((\/\/){0,1}(?P<hostname>[a-zA-Z0-9\.\-]{1,})(\:(?P<port>\d+)){0,1})(\/(?P<service_name>[a-zA-Z\.\-0-9]{1,}(\:(?P<server_type>[a-zA-Z]{1,})){0,1}){0,1}(\/(?P<instance_name>[a-zA-Z0-9]{1,})){0,1}){0,1})$", re.MULTILINE)

text = [
    "jdbc:oracle:thin:@//hostname.example.ru:1521/database.example.ru",
    "jdbc:oracle:thin:@sales-server",
    "jdbc:oracle:thin:@sales-server:3456",
    "jdbc:oracle:thin:@sales-server/sales",
    "jdbc:oracle:thin:@sales-server:80/sales",
    "jdbc:oracle:thin:@sales-server/sales:dedicated/inst1",
    "jdbc:oracle:thin:@sales-server//inst1",
    "jdbc:oracle:thin:@sales-server:1521/sales.us.acme.com",
    "jdbc:oracle:thin:@//sales-server/sales.us.acme.com",
    "jdbc:oracle:thin:@//sales-server.us.acme.com/sales.us.oracle.com",
    "jdbc:oracle:thin:wat@//sales-server.us.acme.com/sales.us.oracle.com",
    "jdbc:oracle:thin:wat/wat@//sales-server.us.acme.com/sales.us.oracle.com",
    "jdbc:oracle:thin:wat/wat@//sales-server.us.acme.com/sales.us.oracle.com:dedicated/instance",
    "jdbc:oracle:thin:wat/wat@//sales-server.us.acme.com//instance",
    "jdbc:oracle:thin:@hostname:1521:DATABASE"
]

matches = jdbc_ezconnect.search(text[0])

username = matches.group('username')
password = matches.group('password')
ezdb_name = matches.group('ezdb_name')
hostname = matches.group('hostname')
port = matches.group('port')
service_name = matches.group('service_name')
server_type = matches.group('server_type')
instance_name = matches.group('instance_name')


print username, password, ezdb_name, hostname, port, service_name, server_type, instance_name

输出:

None None //hostname.example.ru:1521/database.example.ru hostname.example.ru 1521 database.example.ru None None

1 回答

  • 1

    我已经阅读了有关EZCONNECT语法的oracle文档,并编写了正则表达式来解析它 . 第二个字符串是标准jdbc模式的简短版本,因此我将这些正则表达式字符串统一在一个类中以解析每个变体 .

    所以这里是jdbc连接字符串解析器:

    # -*- coding: utf-8 -*-
    
    import re
    
    
    class JDBCParserError(Exception):
        pass
    
    
    class JDBCParser:
        """
        Класс для распарсивания jdbc-строк.
        """
    
        # ezonnect patterns
        jdbc_ezconnect = re.compile("^jdbc:oracle:thin:"
                                    "((?P<username>[a-zA-Z0-9]{1,})"
                                    "([\/](?P<password>[a-zA-Z0-9]{1,})){0,1}){0,1}"
                                    "@"
                                    "(?P<ezdb_name>((\/\/){0,1}"
                                    "(?P<hostname>[a-zA-Z0-9\.\-]{1,})"
                                    "(\:(?P<port>\d+)){0,1})"
                                    "(\/(?P<service_name>[a-zA-Z\.\-0-9]{1,}"
                                    "(\:(?P<server_type>[a-zA-Z]{1,})){0,1}){0,1}"
                                    "(\/(?P<instance_name>[a-zA-Z0-9]{1,})){0,1}){0,1})$")
    
        # jdbc standard pattern - host:port:sid
        jdbc_classic = re.compile("^jdbc:oracle:thin:"
                                  "((?P<username>[a-zA-Z0-9]{1,})"
                                  "([\/](?P<password>[a-zA-Z0-9]{1,})){0,1}){0,1}"
                                  "@"
                                  "(?P<connection_string>("
                                  "(?P<hostname>[a-zA-Z0-9\.\-]+)"
                                  "(\:(?P<port>\d+)))"
                                  "(\:(?P<service_name>[a-zA-Z0-9]+)))$")
    
        username = None
        password = None
        ezdb_name = None
        hostname = None
        port = None
        service_name = None
        instance_name = None
    
        connection_string = None
    
        def __init__(self, jdbc_string):
            ezconnect_match = self.jdbc_ezconnect.search(jdbc_string)
            classic_match = self.jdbc_classic.search(jdbc_string)
    
            if ezconnect_match or classic_match:
                if ezconnect_match:
                    self.username = ezconnect_match.group('username')
                    self.password = ezconnect_match.group('password')
                    self.ezdb_name = ezconnect_match.group('ezdb_name')
                    self.hostname = ezconnect_match.group('hostname')
                    self.port = ezconnect_match.group('port')
                    self.service_name = ezconnect_match.group('service_name')
                    self.instance_name = ezconnect_match.group('instance_name')
                if classic_match:
                    self.username = classic_match.group('username')
                    self.password = classic_match.group('password')
                    self.connection_string = classic_match.group('connection_string')
                    self.hostname = classic_match.group('hostname')
                    self.port = classic_match.group('port')
                    self.service_name = classic_match.group('service_name')
            else:
                raise JDBCParserError("JDBC string not recognized")
    

相关问题