Java中的复杂正则表达式

时间:2015-07-30 00:50:34

标签: java regex url

我有一个相当复杂(对我来说似乎相当复杂)的问题,我在Java中使用正则表达式:

我可以获得任何格式为:

的文本字符串
M:<some text>:D:<either a url or string>:C:<some more text>:Q:<a number>

我开始使用正则表达式来提取 M:/:D:/:C:/:Q:之间的文本:

String pattern2 = "(M:|:D:|:C:|:Q:.*?)([a-zA-Z_\\.0-9]+)";

如果<either a url or string>只是一个字母数字字符串,那就可以正常工作。但是当嵌入的字符串是格式的URL时,它就会崩溃:

TCP://someurl.something:端口

任何人都可以帮我调整上面的reg exp以提取文字之后:D:是网址还是字母数字字符串

以下是一个例子:

public static void main(String[] args) {
    String name = "M:myString1:D:tcp://someurl.com:8989:C:myString2:Q:1";
    boolean matchFound = false;
    ArrayList<String> values = new ArrayList<>();
    String pattern2 = "(M:|:D:|:C:|:Q:.*?)([a-zA-Z_\\.0-9]+)";
    Matcher m3 = Pattern.compile(pattern2).matcher(name);

    while (m3.find()) {
        matchFound = true;
        String m = m3.group(2);
        System.out.println("regex found match:  " + m);
        values.add(m);
    }

}

在上面的示例中,我的结果将是:

myString1
tcp://someurl.com:8989
myString2
1

请注意,字符串可以是可变长度,字母数字,但允许一些字符(例如url格式为://和/或。 - 字符

3 个答案:

答案 0 :(得分:1)

你提到格式是不变的:

M:<some text>:D:<either a url or string>:C:<some more text>:Q:<a number>

捕获组可以使用以下模式为您执行此操作:

"M:(.*):D:(.*):C:(.*):Q:(.*)"

或者您可以使用String.split()模式进行"M:|:D:|:C:|:Q:"。但是,拆分将在第一个索引处返回一个空元素。其他一切都将随之而来。

public static void main(String[] args) throws Exception {
    System.out.println("Regex: ");
    String data = "M:<some text>:D:tcp://someurl.something:port:C:<some more text>:Q:<a number>";
    Matcher matcher = Pattern.compile("M:(.*):D:(.*):C:(.*):Q:(.*)").matcher(data);
    if (matcher.matches()) {
        for (int i = 1; i <= matcher.groupCount(); i++) {
            System.out.println(matcher.group(i));
        }
    }
    System.out.println();

    System.out.println("String.split(): ");
    String[] pieces = data.split("M:|:D:|:C:|:Q:");
    for (String piece : pieces) {
        System.out.println(piece);
    }
}

结果:

Regex: 
<some text>
tcp://someurl.something:port
<some more text>
<a number>

String.split(): 

<some text>
tcp://someurl.something:port
<some more text>
<a number>

答案 1 :(得分:0)

要提取URL /文本部分,您不需要正则表达式。使用

int startPos = input.indexOf(":D:")+":D:".length();
int endPos = input.indexOf(":C:", startPos);
String urlOrText = input.substring(startPos, endPos);

答案 2 :(得分:0)

假设您需要在解析时进行一些验证:

将正则表达式分解为不同的部分:

    String m_regex = "[\\w.]+"; //in jsva a . in [] is just a plain dot
    String url_regex = ".";     //theres a bunch online, pick your favorite.
    String d_regex = "(?:" + url_regex + "|\\p{Alnum}+)"; // url or a sequence of alphanumeric characters
    String c_regex = "[\\w.]+"; //but i'm assuming you want this to be a bit more strictive. not sure.
    String q_regex = "\\d+";    //what sort of number exactly? assuming any string of digits here

    String regex = "M:(?<M>" + m_regex + "):"
                 + "D:(?<D>" + d_regex + "):"
                 + "C:(?<D>" + c_regex + "):"
                 + "Q:(?<D>" + q_regex + ")";
    Pattern p = Pattern.compile(regex);

将模式保存为静态字段并将其编译为静态块可能是个好主意,这样临时正则表达式字符串就不会过度使用基本无用的字段。

然后您可以按名称检索每个部分:

    Matcher m = p.matcher( input );
    if (m.matches()) {
        String m_part = m.group( "M" );
        ...
        String q_part = m.group( "Q" );
    }

您可以通过创建RegexGroup接口/对象更进一步,其中每个实现对象代表具有名称和实际正则表达式的正则表达式的一部分。虽然你绝对失去了简单性,但通过快速浏览更难理解它。 (我不会这样做,只是指出它可能并有自己的好处)