UPDATE: Universal balanced Shortest
In this answer I managed to find a really universal solution through regular expressions:
Clear[ShortestStringBetween]
Options[ShortestStringBetween] = {"IncludeBoundaries" -> False,
"BoundaryOverlaps" -> False};
ShortestStringBetween[str_String, start_String, end_String, OptionsPattern[]] :=
Module[{bInclude = OptionValue["IncludeBoundaries"],
bOvelap = OptionValue["BoundaryOverlaps"]},
Which[
bInclude && Not[bOvelap],
StringCases[str, RegularExpression[
StringTemplate["`START`(?:(?!`END`).(?<!`START`))*`END`"][
<|"START" -> start, "END" -> end|>]]],
Not[bInclude] && Not[bOvelap],
StringCases[str, RegularExpression[
StringTemplate["`START`((?:(?!`END`).(?<!`START`))*)`END`"][
<|"START" -> start, "END" -> end|>]] -> "$1"],
Not[bInclude] && bOvelap,
StringCases[str, RegularExpression[
StringTemplate["(?<=`START`)(?:(?!`END`).(?<!`START`))*(?=`END`)"][
<|"START" -> start, "END" -> end|>]]],
bInclude && bOvelap,
StringCases[str, match : RegularExpression[
StringTemplate["(?<=`START`)(?:(?!`END`).(?<!`START`))*(?=`END`)"][
<|"START" -> start, "END" -> end|>]] :> StringJoin[start, match, end]]
]];
Note that the start and end parameters are directly inserted into RegularExpression and therefore must be regular expressions in the Mathematica format. And since PCRE (on which RegularExpression is based) doesn't support infinite repetition within a lookbehind, the start parameter must be a fixed-length regexp or contain alternations of different but pre-determined lengths (for example, "cat|raccoon"). The end parameter has no such restriction. But I haven't tested how this implementation behaves with non-fixed length parameters.
It works correctly in the all test cases:
front = "Hello";
back = "Goodbye";
str = "blabla ...Hello Hello ... blabla ... Goodbye Goodbye ..";
ShortestStringBetween[str, front, back, "IncludeBoundaries" -> True]
{"Hello ... blabla ... Goodbye"}
front = "tomato";
back = "iconic";
str = "gffghtomatomato12345iconiconictomatomatoiconiconic";
ShortestStringBetween[str, front, back]
{"12345", ""}
front = "NotEnd";
back = "End";
str = "NotEndNotEnd1234NotEnd";
ShortestStringBetween[str, front, back]
ShortestStringBetween[str, front, back, "BoundaryOverlaps" -> True]
{"Not"}
{"Not", "1234Not"}
Original answer
One can use here regular expression with Negative Lookahead (?!regex) Before the Match in the same way as shown in this answer:
text="blabla ...Hello .. blabla .. Hello ... blabla ... Goodbye .. blabla .. Goodbye ... \
blabla ...Hello Hello ... blabla ... blabla ... Goodbye .. blabla .. Goodbye ... ";
StringCases[text, "Hello" ~~ RegularExpression["(?:(?!Hello).)*?"] ~~ "Goodbye"]
{"Hello ... blabla ... Goodbye", "Hello ... blabla ... blabla ... Goodbye"}
Or using pure regexes:
StringCases[text, RegularExpression["Hello(?:(?!Hello).)*?Goodbye"]]
{"Hello ... blabla ... Goodbye", "Hello ... blabla ... blabla ... Goodbye"}
A detailed description of this method can be found here.