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.'s torpor
    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$ Aug 9 '12 at 9:02
  • $\begingroup$ regexes in my answer $\endgroup$ 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$ 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$ 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.

  • 1
    $\begingroup$ Great thanks ;-) So ".{4}entitle.{5}" - is such notation mentioned in docs? It seems I've missed it. $\endgroup$ 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$ 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.'s torpor
    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$ 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.