Edit: It might be easier to instead replace input functions with ones that return TaintedString, unusable as a regular string. But it's easier to write a linter rule that prohibits any unsafe (default) system functions than one which requires safe input functions, I suppose.
Honestly, I think all CS/EE programs should require an OWASP course and that coding should require regular continuing education that includes defensive coding practices for correctness, defined behavior, and security.
Suppose the Table family type their son Bobby's name into a form. The Perl program now has a "tainted" string in memory - "Robert'; DROP TABLE Students --".
The Perl code passes this string through a regex that checks the name is valid. Names can include apostrophes (Miles O'Brien) and hyphens (Jean-Luc Picard) along with spaces and normal ASCII letters, so the regex passes and the string is now untainted.
I think "parse don't validate" doesn't help in this example, but naively the regex would not check whether a name is valid but "extract all parts of the string that are provenly safe".
Which is not reasonable for SQL statements, so someone invented prepared statements.
I think the idea is that the Regex parsing forces the programmer to think about what they're doing with the string and what the requirements for the non-tainted variable are.
For example, a file name string would not allow unescaped directory separators, dots, line breaks, null bytes (I probably got most details wrong here...) and the regex could remove these or extract the substring until the first forbidden character.
Sure, this cannot prevent mistakes.
But the idea, I think, is not to have a variable "safeUserName", instead a "safeDbStatement" one.
In PHP, you can construct objects directly from $_GET/POST (and erase everything from these vars to make sure they are not used directly), then lean on data types to make sure that these values are not used in a wrong place.
ps: ah well, that was fast https://en.wikipedia.org/wiki/Taint_checking#History :) (1989)