How can I find all the (non-overlapping) substrings that start with a specific string of characters (e.g. ">>") and end with another specified string (e.g. "<<"?

For example, when I try the following,

StringCases["ccc>>ccccccc<<cccccc>>cccccccccccccc<<ccccc",">>" ~~ __ ~~ "<<"] 

I get,


but I want

{">>ccccccc<<", ">>cccccccccccccc<<"}.

Furthermore, how do I add a pattern that chooses strings smaller than 10 characters?

  • 4
    $\begingroup$ See Shortest. StringCases["ccc>>ccccccc<<cccccc>>ccccccc<<ccccc", ">>" ~~ Shortest[__] ~~ "<<"] $\endgroup$
    – Jason B.
    Commented Aug 8, 2017 at 1:57
  • $\begingroup$ That works. Thanks. $\endgroup$
    – Miladiouss
    Commented Aug 8, 2017 at 1:59
  • 2
    $\begingroup$ Regex: StringCases["ccc>>ccccccc<<cccccc>>cccccccccccccc<<ccccc", RegularExpression[">>(.{1,9})<<"]] $\endgroup$ Commented Aug 8, 2017 at 2:49
  • 1
    $\begingroup$ How can I learn more about string patterns. I usually enjoy reading the Mathemacia documentations, but their string pattern tutorial is not very engaging and informative. Any recomendations? $\endgroup$
    – Miladiouss
    Commented Aug 9, 2017 at 8:56
  • $\begingroup$ @mpourrah String patterns are converted into regular expressions and then passed to the PCRE library. Hence in order to understand how they work it is worth to learn regexes. There are great resources on the web for this, for example rexegg.com. For testing how string patterns are converted into regexes there is StringPattern`PatternConvert. $\endgroup$ Commented Aug 10, 2017 at 1:53

2 Answers 2


If you are guaranteed that all the opening ">>" and closing "<<" tags are exactly balanced without nesting, then the solutions suggested in the comments will give you the shortest substring between the tags:

StringCases["ccc>>ccccccc<<cccccc>>ccccccc<<ccccc", ">>" ~~ Shortest[___] ~~ "<<"]
{">>ccccccc<<", ">>ccccccc<<"}

(I assume that you wish to obtain all the substrings between the tags including zero-length substrings. If you don't want the latter, replace ___ with __ in the string patterns and * with + in the regexes.)

But in a case of non-balanced or nested tags they will fail to give you the shortest substring between the tags:

StringCases["c>>cc>>ccccccc<<cccccc>>ccccccc<<ccccc", ">>" ~~ Shortest[___] ~~ "<<"]
{">>cc>>ccccccc<<", ">>ccccccc<<"}

In such a situation you can use one of the solutions suggested here:

 ">>" ~~ RegularExpression["(?:(?!>>).)*?"] ~~ "<<"]
{">>ccccccc<<", ">>ccccccc<<"}

If you need only substrings with length smaller than 10 characters you can use either the two-argument form of Repeated or the corresponding regex statement:

(* well-balanced tags without nesting *)
 ">>" ~~ Shortest[Repeated[_, {0, 9}]] ~~ "<<"]
{">>ccccccc<<", ">>ccccccc<<"}
(* non-balanced or nested tags *)
 ">>" ~~ RegularExpression["(?:(?!>>).){0,9}?"] ~~ "<<"]
{">>ccccccc<<", ">>ccccccc<<"}
  • $\begingroup$ When we process this string "xx >>aa >>bbb<< >>bbb<< aa<< yy>>>>dfa<<a<<", actually the following result is expected.But the MMA seem don't support the balance group syntax. $\endgroup$
    – yode
    Commented Aug 8, 2017 at 6:18
  • $\begingroup$ @yode You are asking for the longest substring between balanced tags, this case is addressed here. As I understand, the OP wants the shortest substring. $\endgroup$ Commented Aug 8, 2017 at 6:37
  • $\begingroup$ Ok,I fixed it in the new edit. $\endgroup$
    – yode
    Commented Aug 8, 2017 at 7:32

For the non-balanced or nested tags,we can use ?P

StringCases["xx >>aa >>bbb<< >>bbb<< aa<< yy>>>>dfa<<a<<", 

{">>aa >>bbb<< >>bbb<< aa<<", ">>>>dfa<<a<<"}

Or ?R

StringCases["xx >>aa >>bbb<< >>bbb<< aa<< yy>>>>dfa<<a<<", 

will give a same result.

For the shortest substring we have more easy solution

StringCases["xx >>aa >>bbb<< >>bbb<< aa<< yy>>>>dfa<<a<<", 

{">>aa >>bbb<<", ">>bbb<<", ">>>>dfa<<"}

  • $\begingroup$ It is a good habit to provide a link to the original answer from where the solution comes. Also it is worth to point out that this solution will give the longest substring between balanced tags (i.e. with nested balanced tags) as opposed to my answer which gives the shortest substring between the tags. $\endgroup$ Commented Aug 8, 2017 at 6:46
  • $\begingroup$ Sorry,I just forget the original post,that hard for me to find those link,I alway confusing you and Cuba how to find it so quick.Actually it is from my personal notes.. $\endgroup$
    – yode
    Commented Aug 8, 2017 at 6:57
  • $\begingroup$ "how to find it so quick": in my personal notes I always include a link to the post from where I learned the technique. Without such a link it is difficult to understand the idea if I forgotten how the code works. $\endgroup$ Commented Aug 8, 2017 at 7:03
  • $\begingroup$ @AlexeyPopkov If I have a misunderstand the OP.Do you think I should delete this answer?Actually that post don't include the method based on ?R.. $\endgroup$
    – yode
    Commented Aug 8, 2017 at 7:06
  • $\begingroup$ Since the question is formulated in a confusing way (with insufficient information), your answer is appropriate. You shouldn't delete it. $\endgroup$ Commented Aug 8, 2017 at 7:09

Not the answer you're looking for? Browse other questions tagged or ask your own question.