Two people can write the same pattern and get different results, because a regex is only half the story: its flags decide how it behaves. A handful of them cover almost everything.
The flags that matter
i(case-insensitive):abcalso matchesABCandAbc. Simple, and usually what you want for matching words in mixed-case text.m(multiline): makes^and$match at the start and end of every line rather than only the whole string. Essential for scanning line-oriented text.s(dotall / single-line): makes the dot.match newlines too. Normally.matches any character except a newline, so a pattern meant to span multiple lines silently fails until you set this. This is the flag people most often forget.x(extended / verbose): ignores unescaped whitespace in the pattern and allows comments, so you can lay a complex regex out over several lines with notes. It makes long patterns readable without changing what they match.g(global): find all matches rather than stopping at the first. In many languages this lives on the operation (replace-all, find-all) rather than the pattern, but the idea is the same.
The pair that gets confused
m and s sound alike and do different things. m is about anchors: where ^ and $ land. s is about the dot: whether . crosses newlines. You can want either, both, or neither. A frequent bug is reaching for multiline when you actually needed dotall: you wanted . to span lines, but you enabled the flag that only moved the anchors, and the match still stops at the first newline. When a multi-line match is not working, ask which of the two behaviors you actually need before adding a flag.
Case-insensitive is not the same as Unicode-aware
A case-insensitive flag makes ASCII comparisons behave as expected and does far less than most people assume for anything else. Turkish dotless ı, the German ß, and Greek final sigma all break the assumption that lowercasing is reversible and locale-independent.
Where this matters is a security filter written in one locale and run in another. A pattern that reliably matched a forbidden word in testing can fail against a spelling that is equivalent to a human and different to the matcher — and the request is allowed, correctly, by a rule that is wrong.
If a comparison is a security decision, normalise deliberately before matching rather than delegating it to a flag whose behaviour depends on the runtime, the locale, and the version of the Unicode tables it was compiled against.