4
$\begingroup$

This question already has an answer here:

Am I missing something here? There's no support for abbreviated expressions in StringCases?

StringMatchQ["MATCH", "*H"]

(* True *)

versus

StringCases["MATCH", "*H"]

(* {} *)

$\endgroup$

marked as duplicate by chuy, MarcoB, Dr. belisarius, user9660, m_goldberg Jan 30 '16 at 0:37

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ FWIW I noted this fact here: (6999) $\endgroup$ – Mr.Wizard Jan 29 '16 at 0:23
5
$\begingroup$

You are not missing anything. The documentation for StringCases does not state that it supports abbreviated expressions while StringMatchQ does.

But you can use a string expression.

StringCases["MATCH", ___ ~~ "H"]
(* {"MATCH"} *)
$\endgroup$
5
$\begingroup$

You are correct, StringCases does not support abbreviated string patterns.

Abbreviated string patterns date back to Mathematica version 1. StringExpression was introduced in Mathematica version 5.1, largely obsoleting abbreviated patterns for string manipulation functions. They still remain useful in other contexts such as file and symbol name manipulation.

A Google search reveals that the following functions are explicitly documented to support abbreviated string patterns: StringMatchQ, FileNames, Clear, Protect, Import (ZIP/TAR), FindDevices, NameQ, Directory and Contexts. With the exception of StringMatchQ, none of these functions supports StringExpression.

Thus, StringMatchQ is an anomaly in that it is the only string manipulation function that supports abbreviated string patterns. Mixing abbreviated and StringExpression patterns can be very confusing and lead to unexpected results. Presumably, abbreviated pattern support in StringMatchQ was retained in the interest of backwards compatibility. Newer functions only support the newer syntax and avoid the potential for confusion (e.g. StringCases, introduced alongside StringExpression in version 5.1).

It is possible to convert an abbreviated string pattern into a regular expression by means of the semi-documented function StringPattern`PatternConvert:

abbr[p_] := StringPattern`PatternConvert[p, None, 1][[1]] // RegularExpression

abbr["*H@X"]
(* RegularExpression["(?ms).*?H[^A-Z]+X"] *)

This lets us use abbreviated patterns with StringCases:

StringCases["MATCH", abbr["*H"]]
(* {"MATCH"} *)

StringCases["1X2X3X4X999X", abbr["@X"]]
(* {"1X", "2X", "3X", "4X", "999X"}
$\endgroup$
  • $\begingroup$ There is also Names that support both abbreviated string patterns and StringExpression, for example: Names["System`" ~~ Except[{"$", "`"}] .. ~~ "Style"]. $\endgroup$ – Alexey Popkov Mar 21 '17 at 18:04

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