1
$\begingroup$

I'm trying to understand Mathematica's pattern matching in strings, but I have some doubts.

99% of the time I need to a) check if a match occurs and b) retrieve the matched patterns.

I come from perl, where it is easy to do both in two lines:

"big bad wolf =~ / (.*) /;
print"$1\n"
"bad"

In Mathematica is it possible to do it with just one function call? For now I'm able to do

a = "big bad wolf"
StringMatchQ[a, RegularExpression["big .* wolf"]]
True
StringCases[a, RegularExpression[" (.*) "] -> "$1"]
{"bad"}

As a 2nd question -- how can I retrieve more than one pattern, e.g. from this call:

StringCases[a, RegularExpression["(.*) .* (.*)"]
$\endgroup$
8
  • 1
    $\begingroup$ Quite likely I am misunderstanding your first question, but since you know RegularExpression[] and StringCases[] already, why do they not suit your needs? If nothing is matched, you end up with an empty list. $\endgroup$ Jun 4, 2015 at 8:33
  • $\begingroup$ sorry I wasnt clear... I just wanted to know if in M there is a single function able to return False on no-match, and {\$1,\$2,...} in case of a match ... $\endgroup$
    – alessandro
    Jun 4, 2015 at 8:38
  • $\begingroup$ So, something like With[{s = StringCases[(* stuff *)]}, If[s =!= {}, s, False]]? $\endgroup$ Jun 4, 2015 at 8:44
  • 1
    $\begingroup$ @Mr. Wizard -- that's when m_goldberg is programming for Bob Marley. $\endgroup$
    – bill s
    Jun 4, 2015 at 14:33
  • 1
    $\begingroup$ @Mr.Wizard, et al. Hate to spoil the fun, but -- alas -- I intended to write 'regex work' ()you probably already guessed). At least my conscious mind so intended. The real control center evidently had other things in mind. Never programmed for Marley -- probably missed a good gig :-) $\endgroup$
    – m_goldberg
    Jun 5, 2015 at 2:32

2 Answers 2

5
$\begingroup$

This is a minor variation on the last example in the Examples > Generalizations & Extensions section of RegularExpression,

StringCases["big bad wolf", RegularExpression["(.*) .* (.*)"] -> {"$1", "$2"}]
{{"big", "wolf"}}

Does this work for you?

$\endgroup$
2
  • $\begingroup$ perfectly, thanks! I'm just surprised it doesnt return {"big", "wolf"}: why is it one level deeper? $\endgroup$
    – alessandro
    Jun 5, 2015 at 8:37
  • $\begingroup$ @alessandro That is because of the right hand side of the Rule; if you use RegularExpression["(.*) .* (.*)"] -> foo["$1", "$2"] you will see foo instead. If you want a flat list you could use RegularExpression["(.*) .* (.*)"] -> Sequence["$1", "$2"] or Flatten @ StringCases[ . . . ]. $\endgroup$
    – Mr.Wizard
    Jun 5, 2015 at 13:50
3
$\begingroup$

I think you might be looking for a pattern structure like this:

str = "big bad wolf";
StringCases[str, "big " ~~ x__ ~~ " wolf" -> x]

which returns bad or whatever happens to lie between big and wolf. In the event that there is no match, you get a null {}.

$\endgroup$
2
  • $\begingroup$ Yes, I simply use RegularExpression because, frankly, Wolfram's syntax for RE's is so ugly! (personal opinion :-) $\endgroup$
    – alessandro
    Jun 4, 2015 at 13:23
  • $\begingroup$ @alessandro The Mathematica string pattern syntax is an extension of the native pattern syntax; its strength is that is familiar and very flexible (e.g. extensible with Condition) but like most aspects of Mathematica it is a bit clumsy with Strings. To the extent possible Mathematica actually converts string patterns into regular expressions so if you are comfortable writing them directly you might as well do that, with one caveat: Why is StringExpression faster than RegularExpression? $\endgroup$
    – Mr.Wizard
    Jun 4, 2015 at 15:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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