4
$\begingroup$

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

StringMatchQ["MATCH", "*H"]

(* True *)

versus

StringCases["MATCH", "*H"]

(* {} *)

$\endgroup$
1
  • $\begingroup$ FWIW I noted this fact here: (6999) $\endgroup$
    – Mr.Wizard
    Commented Jan 29, 2016 at 0:23

2 Answers 2

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$
1
  • $\begingroup$ There is also Names that support both abbreviated string patterns and StringExpression, for example: Names["System`" ~~ Except[{"$", "`"}] .. ~~ "Style"]. $\endgroup$ Commented Mar 21, 2017 at 18:04

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