# How to express the notion of "from "a" to the nearest "z"" with patterns?

If I compute this:

 StringCases["abczabvncz", "a" ~~ __ ~~ "z"]


It yields:

{"abczabvncz"}


But I wanted it to take string from "a" to the nearest "z" like:

{"abcz","abvncz"}


I tried to use Repeated[p,n] but the trouble for me is that in the text I'm applying this, there is no guarantee of minimum of maximum between "a" and "z". I would have to use some notion of "nearest z".

• StringCases["abczabvncz", Shortest["a" ~~ __ ~~ "z"]] gives the expected result {"abcz", "abvncz"} Commented May 19 at 0:00

## 3 Answers

str = "abczabvncz";


Borrowing the Shortest-pattern from vindobona (but with a triple underscore)

p = StringPosition[str, Shortest["a" ~~ ___ ~~ "z"]]


{{1, 4}, {5, 10}}

StringTake[str, p]


{"abcz", "abvncz"}

Another example:

str = "azabczabvncz";

p = StringPosition[str, Shortest["a" ~~ ___ ~~ "z"]]


{{1, 2}, {3, 6}, {7, 12}}

StringTake[str, p]


{"az", "abcz", "abvncz"}

StringCases["abczabvncz", "a" ~~ Except["z"] ... ~~ "z"]

StringCases["abczabvncz", RegularExpression["a.*?z"]]

StringCases["abczabvncz", RegularExpression["a[^z]*z"]]

(* and with credit going to vindobona... *)
StringCases["abczabvncz", Shortest["a" ~~ ___ ~~ "z"]]
(* Although, note the ___ rather than __, which would allow you to match when a and z were adjacent. *)


You might also be interested in the Overlaps option for StringCases. For example,

StringCases["abczabvncz", "a" ~~ __ ~~ "z", Overlaps -> All]
(* {"abczabvncz", "abcz", "abvncz"} *)


Using sequence-functions (they get slow with long lists)

c = Characters["azabczabvncz"]


{"a", "z", "a", "b", "c", "z", "a", "b", "v", "n", "c", "z"}

Pre-define pattern for better readability

p = {"a", Except["a"] ..., "z"};


Using SequenceCases

SequenceCases[c, w : p :> StringJoin[w]]


{"az", "abcz", "abvncz"}

Using SequenceSplit (new in 11.3)

SequenceSplit[c, w : p :> StringJoin[w]]


{"az", "abcz", "abvncz"}

Using SequencePosition

q = SequencePosition[c, p]


{{1, 2}, {3, 6}, {7, 12}}

StringJoin @ Take[c, #] & /@ q


{"az", "abcz", "abvncz"}