首页 > 解决方案 > 使用 Java 进行 CLI 模式匹配

问题描述

问题陈述

我正在研究一个用例,其中我有一组设备支持的命令和我想要执行的实际命令。

支持的命令(示例)

config dhcp ip <dhcp-ipaddress> port <dhcp-port-number>
config dhcp ip <dhcp-ipaddress> timeout <time-out-value>
config dhcp ipv4 <dhcp-ipaddress>
config dns ip <dns-ipaddress> port <dns-port-number>
config dns ip <dns-ipaddress> timeout <time-out-value>
config router bgp <bgp-number>
config interface id <interface-id> 
config interface name <interface-name> id <interface-id>

实际命令(示例)

config dhcp ip 1.1.1.1 port 8080
config dhcp ip 1.1.1.2 timeout 120
config dhcp ip 1.1.1.1 timeout 120
config dhcp ip 1.1.1.2 port 8080
config dhcp ipv4 1.1.1.3
config interface id 12 
config interface name abc id 12
config interface id 13 
config interface name xyz id 13

<> 是命令可以采用的值的占位符,其他是关键字。此外,对于给定实体,所有占位符都是相同的,例如,在所有采用 DHCP 地址的命令中将有一个共同的占位符。

预期产出

我必须将“实际命令”与“支持的命令”匹配,然后根据占位符中的值以相同的顺序对它们进行分组,如下所示。

config dhcp ip 1.1.1.1 port 8080
config dhcp ip 1.1.1.1 timeout 120

config dhcp ip 1.1.1.2 timeout 120
config dhcp ip 1.1.1.2 port 8080

config dhcp ipv4 1.1.1.3

config interface id 12 
config interface name abc id 12

config interface id 13 
config interface name xyz id 13

我正在尝试通过正则表达式匹配来实现这一点,但想知道是否有更好的方法来做到这一点。此外,支持的命令和实际命令可能非常庞大,因此需要寻找一种省时的方法。

标签: javaregexalgorithmlucenepattern-matching

解决方案


我猜也许正则表达式在这里不是最好的主意,或者你至少会有一个组合的正则表达式编码方法来解决这个问题。

下面的示例表达式显示“种类”,如何设计正则表达式,或者如果您愿意,您可以如何解决这个问题。

^config d(hcp|ns) ip(v4)? (<[^>]*>|(?:\\d+\\.){3}\\d+)( port| timeout|\\s*$)( <[^>]*>\\s*$| \\d+\\s*$|\\s*$)|config (router|interface) (id|bgp|name) (<[^>]*>\\s*$|<[^>]*> id <[^>]*>\\s*$|\\d+\\s*$|[a-z]+ id \\d+\\s*$|\\s*$)

可以简化为,

^config (dhcp|dns|router|interface) (?:ip|ipv4|id|bgp|name) (<[^>]*>|(?:\\d+\\.){3}\\d+|[a-z]+ id \\d+|\\d+)( port| timeout| id|\\s*)( <[^>]*>\\s*| \\d+\\s*|\\s*)$

演示

这并不复杂,只是写一个这样的表达式很冗长。

测试

import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularExpression{

    public static void main(String[] args){

        final String regex = "^config (dhcp|dns|router|interface) (?:ip|ipv4|id|bgp|name) (<[^>]*>|(?:\\d+\\.){3}\\d+|[a-z]+ id \\d+|\\d+)( port| timeout| id|\\s*)( <[^>]*>\\s*| \\d+\\s*|\\s*)$";
        final String string = "config dhcp ip <dhcp-ipaddress> port <dhcp-port-number>\n"
             + "config dhcp ip <dhcp-ipaddress> timeout <time-out-value>\n"
             + "config dhcp ipv4 <dhcp-ipaddress>\n"
             + "config dns ip <dns-ipaddress> port <dns-port-number>\n"
             + "config dns ip <dns-ipaddress> timeout <time-out-value>\n"
             + "config router bgp <bgp-number>\n"
             + "config interface id <interface-id> \n"
             + "config interface name <interface-name> id <interface-id>\n\n"
             + "config dhcp ip 1.1.1.1 port 8080\n"
             + "config dhcp ip 1.1.1.2 timeout 120\n"
             + "config dhcp ip 1.1.1.1 timeout 120\n"
             + "config dhcp ip 1.1.1.2 port 8080\n"
             + "config dhcp ipv4 1.1.1.3\n"
             + "config interface id 12 \n"
             + "config interface name abc id 12\n"
             + "config interface id 13 \n"
             + "config interface name xyz id 13\n\n"
             + "config dhcp ip 1.1.1.1 port 8080\n"
             + "config dhcp ip 1.1.1.1 timeout 120\n"
             + "config dhcp ip 1.1.1.2 timeout 120\n"
             + "config dhcp ip 1.1.1.2 port 8080\n"
             + "config dhcp ipv4 1.1.1.3\n"
             + "config interface id 12 \n"
             + "config interface name abc id 12\n"
             + "config interface id 13 \n"
             + "config interface name xyz id 13";

        final Pattern pattern = Pattern.compile(regex, Pattern.MULTILINE);
        final Matcher matcher = pattern.matcher(string);

        while (matcher.find()) {
            System.out.println("Full match: " + matcher.group(0));
            for (int i = 1; i <= matcher.groupCount(); i++) {
                System.out.println("Group " + i + ": " + matcher.group(i));
            }
        }


    }
}

输出

Full match: config dhcp ip <dhcp-ipaddress> port <dhcp-port-number>
Group 1: dhcp
Group 2: <dhcp-ipaddress>
Group 3:  port
Group 4:  <dhcp-port-number>
Full match: config dhcp ip <dhcp-ipaddress> timeout <time-out-value>
Group 1: dhcp
Group 2: <dhcp-ipaddress>
Group 3:  timeout
Group 4:  <time-out-value>
Full match: config dhcp ipv4 <dhcp-ipaddress>
Group 1: dhcp
Group 2: <dhcp-ipaddress>
Group 3: 
Group 4: 
Full match: config dns ip <dns-ipaddress> port <dns-port-number>
Group 1: dns
Group 2: <dns-ipaddress>
Group 3:  port
Group 4:  <dns-port-number>
Full match: config dns ip <dns-ipaddress> timeout <time-out-value>
Group 1: dns
Group 2: <dns-ipaddress>
Group 3:  timeout
Group 4:  <time-out-value>
Full match: config router bgp <bgp-number>
Group 1: router
Group 2: <bgp-number>
Group 3: 
Group 4: 
Full match: config interface id <interface-id> 
Group 1: interface
Group 2: <interface-id>
Group 3:  
Group 4: 
Full match: config interface name <interface-name> id <interface-id>

Group 1: interface
Group 2: <interface-name>
Group 3:  id
Group 4:  <interface-id>

Full match: config dhcp ip 1.1.1.1 port 8080
Group 1: dhcp
Group 2: 1.1.1.1
Group 3:  port
Group 4:  8080
Full match: config dhcp ip 1.1.1.2 timeout 120
Group 1: dhcp
Group 2: 1.1.1.2
Group 3:  timeout
Group 4:  120
Full match: config dhcp ip 1.1.1.1 timeout 120
Group 1: dhcp
Group 2: 1.1.1.1
Group 3:  timeout
Group 4:  120
Full match: config dhcp ip 1.1.1.2 port 8080
Group 1: dhcp
Group 2: 1.1.1.2
Group 3:  port
Group 4:  8080
Full match: config dhcp ipv4 1.1.1.3
Group 1: dhcp
Group 2: 1.1.1.3
Group 3: 
Group 4: 
Full match: config interface id 12 
Group 1: interface
Group 2: 12
Group 3:  
Group 4: 
Full match: config interface name abc id 12
Group 1: interface
Group 2: abc id 12
Group 3: 
Group 4: 
Full match: config interface id 13 
Group 1: interface
Group 2: 13
Group 3:  
Group 4: 
Full match: config interface name xyz id 13

Group 1: interface
Group 2: xyz id 13
Group 3: 

Group 4: 
Full match: config dhcp ip 1.1.1.1 port 8080
Group 1: dhcp
Group 2: 1.1.1.1
Group 3:  port
Group 4:  8080
Full match: config dhcp ip 1.1.1.1 timeout 120
Group 1: dhcp
Group 2: 1.1.1.1
Group 3:  timeout
Group 4:  120
Full match: config dhcp ip 1.1.1.2 timeout 120
Group 1: dhcp
Group 2: 1.1.1.2
Group 3:  timeout
Group 4:  120
Full match: config dhcp ip 1.1.1.2 port 8080
Group 1: dhcp
Group 2: 1.1.1.2
Group 3:  port
Group 4:  8080
Full match: config dhcp ipv4 1.1.1.3
Group 1: dhcp
Group 2: 1.1.1.3
Group 3: 
Group 4: 
Full match: config interface id 12 
Group 1: interface
Group 2: 12
Group 3:  
Group 4: 
Full match: config interface name abc id 12
Group 1: interface
Group 2: abc id 12
Group 3: 
Group 4: 
Full match: config interface id 13 
Group 1: interface
Group 2: 13
Group 3:  
Group 4: 
Full match: config interface name xyz id 13
Group 1: interface
Group 2: xyz id 13
Group 3: 
Group 4: 

正则表达式电路

jex.im可视化正则表达式:

在此处输入图像描述


如果您想简化/修改/探索表达式,它已在regex101.com的右上角面板中进行了说明。如果您愿意,您还可以在此链接中观看它如何与一些示例输入匹配。


一种可能更好的方法可能是拆分您的模式并相应地拆分您的样本,然后使用您想要的数据结构编写一些有效的方法,然后通过这些方法提供您的样本。


推荐阅读