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$ – J. M.'s torpor Jun 4 '15 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 '15 at 8:38
  • $\begingroup$ So, something like With[{s = StringCases[(* stuff *)]}, If[s =!= {}, s, False]]? $\endgroup$ – J. M.'s torpor Jun 4 '15 at 8:44
  • 1
    $\begingroup$ @Mr. Wizard -- that's when m_goldberg is programming for Bob Marley. $\endgroup$ – bill s Jun 4 '15 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 '15 at 2:32
4
$\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 '15 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 '15 at 13:50
2
$\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 '15 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 '15 at 15:49

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.