Using patsubst()
m4 provides a search-and-replace function, which can perform substitutions anywhere, including mid-word, called patsubst:
Builtin: patsubst (string, regexp, [replacement])
Searches string for matches of regexp, and substitutes replacement for each match.
This doesn't involve setting up a new definition, so it can't be applied by default to all future input. Instead, you'll have to "sandwich" the full input text inside the function call:
patsubst(dnl
[...]
Saturday
[...]
,`Sat',`Cat')dnl
Using changeword()
m4 also provides changeword:
A file being processed by m4 is split into quoted strings, words (potential macro names) and simple tokens (any other single character). Initially a word is defined by the following regular expression:
[_a-zA-Z][_a-zA-Z0-9]*
Using changeword, you can change this regular expression:
Unfortunately, the changeword function is non-standard. It's only available if you requested it with --enable-changeword at compile time.
With it enabled, you could eg. force m4 to only accept three-letter words.
define(`Sat',`Cat')dnl
changeword(`[A-Za-z][a-z]?[a-z]?')dnl
Saturday
But changeword has additional problems:
regex must obey the constraint that every prefix of the desired final pattern is also accepted by the regular expression.
[...]
Tightening the lexical rules is less useful, because it will generally make some of the builtins unavailable.
The above pattern would prevent further definitions (it only even recognises dnl because that's exactly three letters). So as well as being non-standard, it's not really suited to what you're trying to do.