08 · String & Text Processing¶
Module 02 introduced the two text types, char and string. This module
covers the functions you'll actually use to build, inspect, and transform
text — most work on both types, with a few differences worth knowing.
Building text: concatenation and formatting¶
>> first = "Alice"; last = "Smith";
>> full = first + " " + last % string concatenation with +
full =
"Alice Smith"
>> full2 = strcat(first, " ", last) % works for char AND string
full2 =
"Alice Smith"
For formatted output with embedded values, sprintf (build a string) and
fprintf (print directly) use C-style format specifiers:
>> name = "Bob"; age = 30;
>> msg = sprintf('%s is %d years old', name, age)
msg =
'Bob is 30 years old'
>> fprintf('%s is %d years old\n', name, age)
Bob is 30 years old
| Specifier | Meaning |
|---|---|
%s |
text (char or string) |
%d |
integer |
%f |
floating point, e.g. %.2f for 2 decimal places |
\n |
newline |
sprintf returns a char array (not a string), regardless of what type
its arguments were — worth knowing if you chain sprintf's result into
something that specifically expects a string.
Inspecting text¶
>> s = "Hello, World!";
>> length(s) % total character count
ans =
13
>> upper(s)
ans =
"HELLO, WORLD!"
>> lower(s)
ans =
"hello, world!"
>> strtrim(" padded ") % remove leading/trailing whitespace
ans =
"padded"
Searching within text¶
>> s = "The quick brown fox";
>> contains(s, "quick")
ans =
logical
1
>> startsWith(s, "The")
ans =
logical
1
>> strfind(s, "o") % ALL starting positions of a match (numeric array)
ans =
13 17
contains, startsWith, and endsWith return a clean logical true/
false and are the modern, readable choice for a yes/no check. strfind
instead returns every index where a match starts — useful when you need
where a substring occurs, not just whether it does.
Splitting and joining¶
>> csv_line = "Alice,30,Boston";
>> parts = split(csv_line, ",")
parts =
3x1 string array
"Alice"
"30"
"Boston"
>> strjoin(["Alice", "30", "Boston"], " | ")
ans =
'Alice | 30 | Boston'
split on a string returns a column of pieces by default, not a row
— a common shape surprise if you then try to concatenate the result with
something else expecting a row vector. strjoin requires a cell array
of char, or a string array, and always returns char.
Replacing text¶
>> s = "The cat sat on the mat";
>> replace(s, "at", "og")
ans =
"The cog sog on the mog"
>> regexprep(s, '[aeiou]', '*') % regex-based replace
ans =
"Th* c*t s*t *n th* m*t"
replace does simple literal substring replacement; regexprep accepts a
full regular expression pattern for anything more sophisticated (multiple
patterns, character classes, capture groups).
Converting between text and numbers¶
>> str2double("42.5")
ans =
42.5000
>> num2str(42.5)
ans =
'42.5'
>> num2str(pi, 4) % second argument controls significant digits
ans =
'3.142'
str2double on text that isn't a valid number returns NaN rather than
erroring — always worth checking for when parsing user-provided or
file-sourced text:
Comparing text¶
>> strcmp("hello", "hello") % exact comparison, case-SENSITIVE
ans =
logical
1
>> strcmp("Hello", "hello")
ans =
logical
0
>> strcmpi("Hello", "hello") % the 'i' suffix means case-INsensitive
ans =
logical
1
Plain == also works for comparing two string values directly (unlike
char, where == compares character-by-character and requires equal
lengths) — "hello" == "hello" gives true, but 'hello' == 'hi' errors
because the char arrays have different lengths. strcmp/strcmpi work
consistently for both types and are the safer default habit.
Regular expressions with regexp¶
regexp's behavior depends heavily on its trailing option string
('match', 'tokens', 'start', 'names', etc.) — 'match' returns the
actual matched text (in a cell array), which is the most common case for
simple extraction tasks.
Text processing cheat sheet¶
| Task | Function |
|---|---|
| Concatenate | a + b (string), strcat(a, b), [a, b] (char) |
| Format with values | sprintf('%s: %d', name, val) |
| Length | length(s) |
| Upper/lower case | upper(s), lower(s) |
| Trim whitespace | strtrim(s) |
| Contains / starts / ends | contains, startsWith, endsWith |
| Find position(s) | strfind(s, pattern) |
| Split | split(s, delimiter) |
| Join | strjoin(cellOrStringArray, delimiter) |
| Replace (literal) | replace(s, old, new) |
| Replace (regex) | regexprep(s, pattern, replacement) |
| Text -> number | str2double(s) (returns NaN on failure) |
| Number -> text | num2str(n) |
| Compare (exact / case-insensitive) | strcmp(a, b), strcmpi(a, b) |
| Regex extraction | regexp(s, pattern, 'match') |
How It Actually Works¶
String and character comparisons in MATLAB ultimately bottom out in
element-wise numeric comparison, because char values are numbers —
'A' == 65 returns true because a char array's elements are 16-bit
UTF-16 code unit values that happen to display as glyphs. strcmp(a,b)
isn't magic: it checks that both arguments have identical class and size
and then does the equivalent of all(double(a) == double(b)), returning a
single logical rather than an element-wise array like == would if you
tried to compare char arrays of different lengths directly (which
errors, since == requires matching sizes or scalar expansion).
Regular expressions (regexp/regexprep) are handled by a PCRE-style
regex engine compiled into MATLAB, not the interpreter itself — pattern
compilation (parsing the regex string into an internal automaton) happens
on every regexp call unless you're using the same pattern repeatedly in
a tight loop, in which case that recompilation cost is paid every
iteration; this is a real, measurable difference from vectorized numeric
operations, since regex matching is inherently a sequential
character-by-character automaton walk, not something that vectorizes
across array elements the way arithmetic does.
sprintf/fprintf format specifiers (%d, %f, %s) drive a C-style
formatting engine underneath — %d on a non-integer double doesn't
error, it falls back to a general numeric format, because MATLAB's
sprintf inspects the actual value's type at call time rather than
enforcing the specifier's implied type at compile time the way C's
printf would (undefined behavior in C, a graceful fallback in MATLAB).
Note: based on documented behavior of MATLAB's string/regex engine, not run in MATLAB itself; character-code claims cross-checked against the Unicode/UTF-16 standard.
🔀 See this in another language¶
Exercise¶
Given record = "Alice,29,Engineer", use split to break it into three
pieces on the comma, convert the age piece to a number with str2double,
and use sprintf to build the sentence "Alice is 29 years old and works
as an Engineer.". Then take the sentence "The rain in Spain stays mainly
in the plain" and use regexp with pattern '\w*ain\w*' and the
'match' option to extract every word ending in "ain".