如何使用正则表达式提取子字符串

asd*_*asd 351 java regex string text-extraction

我有一个字符串,其中包含两个单引号,即'字符.在单引号之间是我想要的数据.

如何编写正则表达式以从以下文本中提取"我想要的数据"?

mydata = "some string with 'the data i want' inside";
Run Code Online (Sandbox Code Playgroud)

Mar*_*ers 522

假设您希望单引号之间的部分,请使用此正则表达式Matcher:

"'(.*?)'"
Run Code Online (Sandbox Code Playgroud)

例:

String mydata = "some string with 'the data i want' inside";
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(mydata);
if (matcher.find())
{
    System.out.println(matcher.group(1));
}
Run Code Online (Sandbox Code Playgroud)

结果:

the data i want

  • 当您预期出现多次出现时,将"if"替换为"while" (32认同)
  • @mFontoura group(0)将返回与外部''的完整匹配.group(1)返回''without the'之间的内容. (23认同)
  • 请注意,此代码示例需要matcher.find()才能工作.如果调用matcher.group(1),则无法调用此方法将导致"找不到匹配"异常. (13认同)
  • 该死的...我总是忘记非贪婪的修饰符:( (12认同)
  • @Larry这是一个迟到的回复,但是?在这种情况下是非贪婪的修饰符,因此对于'this'是带引号的'my'数据'它会提前停止并返回`is`而不是匹配尽可能多的字符并返回`是'my'数据,这是默认行为. (5认同)
  • 为什么Mark会在这种情况下使用问号?是不是.*匹配0或更多?那么如果两个引文之间有一个空字符串,那么它会匹配吗? (4认同)

Beo*_*orn 67

你不需要正则表达式.

将apache commons lang添加到您的项目(http://commons.apache.org/proper/commons-lang/),然后使用:

String dataYouWant = StringUtils.substringBetween(mydata, "'");
Run Code Online (Sandbox Code Playgroud)

  • 您必须考虑如何分发您的软件.如果它类似于webstart,那么添加Apache commons只是为了使用这一功能是不明智的.但也许不是.除了Apache commons还有很多东西可以提供.即使很难知道正则表达式,你必须小心何时使用它.正则表达式可能非常难以读取,编写和调试.鉴于某些上下文使用它可能是更好的解决方案. (11认同)
  • 就像买车去5英里(当你一年只旅行一次). (5认同)
  • 有时StringUtils已经存在,在这种情况下,这个解决方案更加清晰和可读. (3认同)

Nik*_*las 16

从 Java 9 开始

从此版本开始,您可以使用一种Matcher::results不带参数的新方法,该方法能够轻松返回代表匹配操作结果的Stream<MatchResult>位置MatchResult,并提供读取匹配组等内容(此类自 Java 1.5 起就已为人所知)。

String string = "Some string with 'the data I want' inside and 'another data I want'.";

Pattern pattern = Pattern.compile("'(.*?)'");
pattern.matcher(string)
       .results()                       // Stream<MatchResult>
       .map(mr -> mr.group(1))          // Stream<String> - the 1st group of each result
       .forEach(System.out::println);   // print them out (or process in other way...)
Run Code Online (Sandbox Code Playgroud)

上面的代码片段的结果是:

the data I want
another data I want
Run Code Online (Sandbox Code Playgroud)

if (matcher.find())与程序、检查和处理相比,最大的优势在于当一个或多个结果可用时易于使用while (matcher.find())


小智 11

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

public class Test {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(".*'([^']*)'.*");
        String mydata = "some string with 'the data i want' inside";

        Matcher matcher = pattern.matcher(mydata);
        if(matcher.matches()) {
            System.out.println(matcher.group(1));
        }

    }
}
Run Code Online (Sandbox Code Playgroud)

  • 编号组(0)具有特殊含义,捕获组从索引组(1)开始(即答案中组(1)正确)."捕获组从左到右编入索引,从一开始.组零表示整个模式" - 来源:https://docs.oracle.com/javase/8/docs/api/java/util/regex/Matcher. HTML#组内部 - (3认同)
  • 的System.out.println(matcher.group(0)); <---零基指数 (2认同)
  • 请记住,“matches()”尝试匹配整个字符串,因此如果模式的开头和结尾处没有“.*”,它将找不到任何内容。 (2认同)

Deb*_*ski 9

因为你还勾选了Scala,这是一个没有正则表达式的解决方案,可以轻松处理多个带引号的字符串:

val text = "some string with 'the data i want' inside 'and even more data'"
text.split("'").zipWithIndex.filter(_._2 % 2 != 0).map(_._1)

res: Array[java.lang.String] = Array(the data i want, and even more data)
Run Code Online (Sandbox Code Playgroud)

  • 这么可读的解决方案,这就是为什么人们喜欢斯卡拉我相信:) (4认同)
  • 为什么不只是`.split('\'').get(2)`或者Java中的某种程度?如果您认为这是一个可读的解决方案,我认为您可能需要进行大脑扫描 - 看起来有人试图为我做一些高尔夫代码. (3认同)

Boh*_*ian 9

这有一个简单的单行:

String target = myData.replaceAll("[^']*(?:'(.*?)')?.*", "$1");
Run Code Online (Sandbox Code Playgroud)

通过使匹配组可选,这也适用于在这种情况下通过返回空白而找不到引号.

查看现场演示.


Zeh*_*n12 5

String dataIWant = mydata.replaceFirst(".*'(.*?)'.*", "$1");
Run Code Online (Sandbox Code Playgroud)

  • 你能解释一下你的答案吗?比如为什么要使用 `replaceFirst` ?为什么是“$1”? (2认同)