# Grabbing a number of characters around a string pattern

If I have some string data:

text = StringTake[ExampleData[{"Text", "DeclarationOfIndependence"}], 400]


"When in the Course of human events, it becomes necessary for one people to dissolve the political bands which have connected them with another, and to assume, among the Powers of the earth, the separate and equal station to which the Laws of Nature and of Nature's God entitle them, a decent respect to the opinions of mankind requires that they should declare the causes which impel them to the sepa"

This is what I use to find a specific pattern inside and grab a bit more data around it:

StringCases[text, (y__ /;StringLength[y] == 4) ~~ "entitle" ~~ x__ /;StringLength[x] == 5]

{"God entitle them"}


Are there any alternatives, desirably neater ones? Maybe something with regular expressions?

-
So StringTake[text, First[StringPosition[text, "entitle"]] + {-4, 5}] isn't neat? –  Ｊ. Ｍ. Aug 9 '12 at 8:54
@J.M. It is, you should post it as an answer - I am looking for tidbits like this ;-) Hoping to get something with regular expressions too. –  Vitaliy Kaurov Aug 9 '12 at 9:02
regexes in my answer –  belisarius Aug 9 '12 at 9:27

Per Vitaliy's request:

With[{before = 4, after = 5},
StringTake[text, First[StringPosition[text, "entitle"]] + {-before, after}]]


yields "God entitle them".

-

Using regular expressions

f[text_, string_, before_, after_] :=
StringCases[text, RegularExpression[".{" <> ToString@before <> "}" <>
string <> ".{" <> ToString@after <> "}"]]

f[text, "entitle", 4, 5]

(*{"God entitle them"}*)


A more compact implementation of the function f[] is as follows:

f[text_String, string_String, before_Integer, after_Integer] :=
StringCases[text, RegularExpression[ToString[StringForm[
".{1}" <> string <> ".{2}", before, after]]]]


The ToString[] is needed here since StringForm[], contrary to how it is named, does not return a String[] object, and thus a conversion has to be done.

-
Great thanks ;-) So ".{4}entitle.{5}" - is such notation mentioned in docs? It seems I've missed it. –  Vitaliy Kaurov Aug 9 '12 at 9:38
@VitaliyKaurov The Regexp docs in the Mma help system are good, but not enough to learn regexes from zero. –  belisarius Aug 9 '12 at 9:49
@VitaliyKaurov The documentation mentions that Mathematica's regular expressions are implemented using PCRE. The PCRE and Perl regex man pages accurately document Mathematica's regex features. –  WReach Aug 9 '12 at 12:18
Here's an alternative implementation: f[text_, string_, before_, after_] := StringCases[text, RegularExpression[ToString[StringForm[".{1}" <> string <> ".{2}", before, after]]]] –  Ｊ. Ｍ. Aug 12 '12 at 4:59
@J.M. StringForm is one of those zillions of little Mma functions that make life easier, but I keep forgetting. As it is a real improvement (at least in readability), please consider to post an answer or edit mine. –  belisarius Aug 12 '12 at 5:04
StringCases[text, x___ ~~ "entitle" ~~ y___ :>
StringTake[x, -4] ~~ "entitle" ~~ StringTake[y, 5]]


or

StringCases[text, Repeated[_, 4] ~~ "entitle" ~~ Repeated[_, 5]]


Generalizing:

paddedString1[text_, string_, left_, right_] :=
StringCases[text,  x___ ~~ string ~~ y___ :>
StringTake[x, -left] ~~ string ~~ StringTake[y, right]]


and

paddedString2[text_, string_, left_, right_] :=
StringCases[text, Repeated[_, {left}] ~~ string ~~ Repeated[_, {right}]]

-
Interesting twist, thanks ;-) –  Vitaliy Kaurov Aug 9 '12 at 10:01
I think the last one should be Repeated[_, {left}] ~~ string ~~ Repeated[_, {right}]? Repeated[_, n] means "repeated up to n times"; Repeated[_, {n}] is exactly n. –  Oleksandr R. Aug 10 '12 at 17:32
@OleksandrR., you are right ... Thank you. I thought --wrongly -- that n versus {n} would not make a difference for the pattern _ and chose to save some keystrokes. –  kguler Aug 11 '12 at 0:20
@Oleksandr when would the original produce an incorrect result? I find the behavior of the original highly desirable in that it gracefully handles sub-strings at the beginning and end of the text. If this were my question I would Accept this answer (in its original form) for that reason. –  Mr.Wizard Aug 11 '12 at 7:09
kguler, by the way, I happened to check your profile and you've been here every single day since the beginning. I don't know whether I should congratulate you or arrange an intervention. –  Mr.Wizard Aug 11 '12 at 7:22