添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I have a string that has two single quotes in it, the ' character. In between the single quotes is the data I want.

How can I write a regex to extract "the data i want" from the following text?

mydata = "some string with 'the data i want' inside";

Assuming you want the part between single quotes, use this regular expression with a Matcher:

"'(.*?)'"

Example:

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));

Result:

the data i want mind that matcher.find() is needed for this code sample to work. failing to call this method will result in a "No match found" exception when matcher.group(1) is called. – rexford Jul 31, 2014 at 14:03 @mFontoura group(0) would return the complete match with the outer ' '. group(1) returns what is in-between the ' ' without the ' ' themselves. – tagy22 Feb 19, 2015 at 14:34 @Larry this is a late reply, but ? in this case is non-greedy modifier, so that for this 'is' my 'data' with quotes it would stop early and return is instead of matching as many characters as possible and return is' my 'data, which is the default behavior. – Timekiller Sep 12, 2016 at 14:08

You don't need regex for this.

Add apache commons lang to your project (http://commons.apache.org/proper/commons-lang/), then use:

String dataYouWant = StringUtils.substringBetween(mydata, "'");
                You have to take into account how your software will be distributed. If it is something like a webstart it's not wise to add Apache commons only to use this one functionality. But maybe it isn't.    Besides Apache commons has a lot more to offer. Even tough it's good to know regex, you have to be carefull on when to use it.    Regex can be really hard to read, write and debug. Given some context using this could be the better solution.
– Beothorn
                Apr 13, 2015 at 14:41
                Sometimes StringUtils is already there, in those cases this solution is much cleaner and readable.
– Gábor Nagy
                Sep 14, 2016 at 11:58
                While substring looks for a specific string or value, regex looks for a format. It's more and more dynamic. You need regex, if you are looking for a pattern instead of a special value.
– burak
                Sep 19, 2017 at 10:20
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));
                No. group(0) has special meaning, capturing groups start at index group(1)  (i.e. group(1) is correct in the answer).   "Capturing groups are indexed from left to right, starting at one. Group zero denotes the entire pattern" - Source: docs.oracle.com/javase/8/docs/api/java/util/regex/…
– Apriori
                Apr 18, 2017 at 6:48
                Bear in mind that matches() tries to match entire string, so if you don't have ".*" at the beginning and end of your pattern, it won't find anything.
– oneturkmen
                Mar 9, 2021 at 17:42

There's a simple one-liner for this:

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

By making the matching group optional, this also caters for quotes not being found by returning a blank in that case.

See live demo.

Since Java 9

As of this version, you can use a new method Matcher::results with no args that is able to comfortably return Stream<MatchResult> where MatchResult represents the result of a match operation and offers to read matched groups and more (this class is known since 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...)

The code snippet above results in:

the data I want
another data I want

The biggest advantage is in the ease of usage when one or more results is available compared to the procedural if (matcher.find()) and while (matcher.find()) checks and processing.

Because you also ticked Scala, a solution without regex which easily deals with multiple quoted strings:

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)
                Why not just .split('\'').get(2) or something to that extent in Java? I think you may need to get a brain scan if you think that's a readable solution - it looks like someone was trying to do some code golf to me.
– ArtOfWarfare
                Apr 10, 2017 at 17:05

the actual regexp is: /'([^']+)'/

if you use the non greedy modifier (as per another post) it's like this:

mydata.match(/'(.*?)'/)[1]

it is cleaner.

Apache Commons Lang provides a host of helper utilities for the java.lang API, most notably String manipulation methods. In your case, the start and end substrings are the same, so just call the following function.

StringUtils.substringBetween(String str, String tag)
  

Gets the String that is nested in between two instances of the same String.

If the start and the end substrings are different then use the following overloaded method.

StringUtils.substringBetween(String str, String open, String close)
  

Gets the String that is nested in between two Strings.

If you want all instances of the matching substrings, then use,

StringUtils.substringsBetween(String str, String open, String close)
  

Searches a String for substrings delimited by a start and end tag, returning all matching substrings in an array.

For the example in question to get all instances of the matching substring

String[] results = StringUtils.substringsBetween(mydata, "'", "'");
ticks findFirstIn mydata match {
    case Some(ticks(inside)) => println(inside)
    case _ => println("nothing")
for (ticks(inside) <- ticks findAllIn mydata) println(inside) // multiple matches
val Some(ticks(inside)) = ticks findFirstIn mydata // may throw exception
val ticks = ".*'([^']*)'.*".r    
val ticks(inside) = mydata // safe, shorter, only gets the first set of ticks
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-io</artifactId>
    <version>1.3.2</version>
</dependency>

And below code works.

StringUtils.substringBetween(String mydata, String "'", String "'")
i use while loop to store all matches substring in the array  if you use

if (matcher.find()) System.out.println(matcher.group(1));

you will get on matches substring so you can use this to get all matches substring

Matcher m = Pattern.compile("[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\\.[a-zA-Z0-9-.]+").matcher(text);
   // Matcher  mat = pattern.matcher(text);
    ArrayList<String>matchesEmail = new ArrayList<>();
        while (m.find()){
            String s = m.group();
            if(!matchesEmail.contains(s))
                matchesEmail.add(s);
    Log.d(TAG, "emails: "+matchesEmail);

Some how the group(1) didnt work for me. I used group(0) to find the url version.

Pattern urlVersionPattern = Pattern.compile("\\/v[0-9][a-z]{0,1}\\/");
Matcher m = urlVersionPattern.matcher(url);
if (m.find()) { 
    return StringUtils.substringBetween(m.group(0), "/", "/");
return "v0";