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?

  • 2
    $\begingroup$ So StringTake[text, First[StringPosition[text, "entitle"]] + {-4, 5}] isn't neat? $\endgroup$ – J. M. will be back soon Aug 9 '12 at 8:54
  • $\begingroup$ @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. $\endgroup$ – Vitaliy Kaurov Aug 9 '12 at 9:02
  • $\begingroup$ regexes in my answer $\endgroup$ – Dr. 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".

StringCases[text, x___ ~~ "entitle" ~~ y___ :> 
   StringTake[x, -4] ~~ "entitle" ~~ StringTake[y, 5]]


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


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


paddedString2[text_, string_, left_, right_] := 
 StringCases[text, Repeated[_, {left}] ~~ string ~~ Repeated[_, {right}]]
  • $\begingroup$ Interesting twist, thanks ;-) $\endgroup$ – Vitaliy Kaurov Aug 9 '12 at 10:01
  • 1
    $\begingroup$ 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. $\endgroup$ – Oleksandr R. Aug 10 '12 at 17:32
  • $\begingroup$ @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. $\endgroup$ – kglr Aug 11 '12 at 0:20
  • $\begingroup$ @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. $\endgroup$ – Mr.Wizard Aug 11 '12 at 7:09
  • 1
    $\begingroup$ 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. $\endgroup$ – Mr.Wizard Aug 11 '12 at 7:22

Using regular expressions

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

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

(*{"God entitle them"}*)

(added by J. M.)

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.

  • $\begingroup$ Great thanks ;-) So ".{4}entitle.{5}" - is such notation mentioned in docs? It seems I've missed it. $\endgroup$ – Vitaliy Kaurov Aug 9 '12 at 9:38
  • 2
    $\begingroup$ @VitaliyKaurov The Regexp docs in the Mma help system are good, but not enough to learn regexes from zero. $\endgroup$ – Dr. belisarius Aug 9 '12 at 9:49
  • 3
    $\begingroup$ @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. $\endgroup$ – WReach Aug 9 '12 at 12:18
  • 1
    $\begingroup$ Here's an alternative implementation: f[text_, string_, before_, after_] := StringCases[text, RegularExpression[ToString[StringForm[".{`1`}" <> string <> ".{`2`}", before, after]]]] $\endgroup$ – J. M. will be back soon Aug 12 '12 at 4:59
  • $\begingroup$ @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. $\endgroup$ – Dr. belisarius Aug 12 '12 at 5:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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