【问题标题】:Java Regex: Text extraction into an array listJava Regex:将文本提取到数组列表中
【发布时间】:2022-01-05 13:19:06
【问题描述】:

我正在努力使用一个简单的正则表达式,我似乎无法正确处理。

我有一些这样的文字:

This comment is great **[@madeUpUser1](/madeUpUser1)** You said something similar did you mate? **[@madeUpUser2](/madeUpUser2)**

我想最终得到一个数组列表,其中包含括号之间的用户名,即:

0.madeUpUser1
1.madeUpUser2

这是我目前的代码:

List<String> matches = Pattern.compile("\\((.+?)\\)")
        .matcher("This comment is great **[@madeUpUser1](/madeUpUser1)** You said something similar did you mate? **[@madeUpUser2](/madeUpUser2)**")
        .results()
        .map(MatchResult::group)
        .collect(Collectors.toList());

但是我得到的是这样的:

0."(/madeUpUser1)"
1."(/madeUpUser2)"

再次,我想要的地方:

0.madeUpUser1
1.madeUpUser2

即没有括号,也没有正斜杠

谁能解释一下我的正则表达式有什么问题?

【问题讨论】:

  • 你可以试试(?&lt;=\(\/)[^)]+(?=\))
  • 我建议调整问题的标题。到目前为止,接受的答案没有“文本提取到数组列表”的解决方案,只有一个可以用来做到这一点的正则表达式。也许它应该听起来像“在括号之间提取字符串,不包括第一个下划线”,或者类似的东西。

标签: java regex


【解决方案1】:

试试这个正则表达式:

(?<=\\(/)[^)]+(?=\\))

Click for Demo

说明

  • (?&lt;=\\(/) - 正向向后看,以确保当前位置前面有 (/

  • [^)]+ - 匹配任何不是)的字符的1次或多次出现(尽可能多)

  • (?=\\)) - 正向前瞻以确保当前位置后跟)

使用您使用的正则表达式\\((.+?)\\),会发生以下情况:

  • \\( - 匹配左括号 (
  • (.+?) - 匹配任何字符(换行符除外)1 次或多次,尽可能少。此子模式将继续扩展匹配,直到到达)。这就是为什么它匹配括号之间的所有内容(甚至是/
  • \\) - 匹配右括号 )

【讨论】:

  • 哇,感谢您的快速响应,这按预期工作。我可能会很痛苦,请问您能否为我解释一下,以便我能理解它为什么有效?再次非常感谢您!
  • 性能方面,Wiktor 的回答更有效。我使用了更昂贵的环视。
【解决方案2】:

您可以匹配](/,然后捕获() 之外的任何零个或多个字符,直到下一个),并仅收集第1 组匹配项:

import java.util.*;
import java.util.regex.*;
import java.util.stream.Collectors;


class Test
{
    public static void main (String[] args) throws java.lang.Exception
    {
        String text = "This comment is great **[@madeUpUser1](/madeUpUser1)** You said something similar did you mate? **[@madeUpUser2](/madeUpUser2)**";

        Pattern p = Pattern.compile("]\\(/([^()]*)\\)");
        List<String> results = p.matcher(text)
            .results()
            .map(mr -> mr.group(1))
            .collect(Collectors.toList());
        
        // Or, to get a string array:
        // String[] results = p.matcher(text).results().map(mr -> mr.group(1)).toArray(String[]::new);

        for (String x: results) {
            System.out.println(x);
        }
    }
}

请参阅online demo。输出:

madeUpUser1
madeUpUser2

请参阅regex demo详情

  • ]\(/ - ])/ 字符串
  • ([^()]*) - 捕获组 1:除 )( 之外的任何零个或多个字符
  • \) - ) 字符。

【讨论】:

    【解决方案3】:

    您可以使用捕获组,并匹配外部括号/方括号:

    \(/([^\s()]+)\)
    
    • \(/匹配(/
    • ( 捕获第 1 组
      • [^\s()]+ 匹配 1+ 个字符而不是空格字符或 ( )
    • )关闭第一组
    • \)匹配)

    Regex demo

    List<String> matches = Pattern.compile("\\(/([^\\s()]+)\\)")
        .matcher("This comment is great **[@madeUpUser1](/madeUpUser1)** You said something similar did you mate? **[@madeUpUser2](/madeUpUser2)**")
        .results()
        .map(m -> m.group(1))
        .collect(Collectors.toList());
    
    for (String s : matches)
        System.out.println(s);
    

    输出

    madeUpUser1
    madeUpUser2
    

    或者在示例中,方括号之间的字符串似乎是相同的,因此使用相同代码的另一个选项可能是:

    \[@([^\s\]\[]+)]
    
    • \[@ 匹配 [@
    • ( 捕获第 1 组
      • [^\s\]\[]+ 匹配 1+ 字符而不是空格字符或 [ ]
    • )关闭第一组
    • ]匹配]

    Regex demo | Java demo

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多