Mixing these up is one of the most common sources of "why isn't my pattern matching" confusion: a glob and a regex can use the same character (*) to mean two completely different things.

Globbing: expanded by the shell, before the command runs

When you type ls *.txt, the shell - not ls - expands *.txt into a list of matching filenames before ls ever sees them. Run echo *.txt in a directory with matching files to see this directly: echo never gets the string *.txt, it gets the already-expanded list.

Pattern Matches
* Any characters (not including a leading dot, by default)
? Exactly one character
[abc] One character: a, b, or c
[a-z] One character in the range a to z
[^abc] One character that is not a, b, or c
{jpg,png} Brace expansion (Bash extension, not strictly a glob): one of the listed alternatives
ls *.log             # every file ending in .log
ls report-??.csv     # report-01.csv, report-42.csv, not report-1.csv
ls image.{jpg,png}   # image.jpg and image.png, if either exists

If a glob matches nothing, Bash's default behavior is to pass the literal pattern string through unchanged - a frequent source of confusing "No such file" errors when a command receives *.txt as a literal argument because nothing matched. shopt -s nullglob changes that behavior to expand to nothing instead, which is often what scripts actually want - see Shell Scripting.

Regex: matched by the tool, against text content

A regular expression is evaluated by whatever program you pass it to (grep, sed, awk, find -regex) against the content of lines or strings - not filenames, and not expanded by the shell first.

Pattern Matches
. Any single character
* Zero or more of the previous character
+ One or more (extended regex only - see below)
^ / $ Start / end of line
[abc] One character: a, b, or c (same idea as globs, different context)
| Alternation - "either side" (extended regex only)
grep "^root:" /etc/passwd
root:x:0:0:root:/root:/bin/bash

Note that . in a regex means "any character," while in a glob it has no special meaning at all - *.txt as a glob matches files ending in .txt literally, but .*\.txt as a regex means "any characters, then a literal dot, then txt."

Basic vs. extended regex

grep defaults to basic regular expressions (BRE), where +, ?, and | are literal characters unless escaped (\+, \?, \|). Extended regular expressions (ERE), used by grep -E (or egrep, deprecated in favor of -E) and awk, treat them as metacharacters without escaping:

grep 'colou\?r' file.txt     # BRE: matches "color" or "colour"
grep -E 'colou?r' file.txt   # ERE: same result, no backslash needed

sed follows BRE by default too, with a -E (GNU) or -r flag for ERE depending on version - check man sed on the system you're using, since this is one of the more common cross-distro inconsistencies.

Quoting matters for both

Always quote glob and regex patterns you don't want the shell to expand itself:

grep "[0-9]+" file.txt    # safe: the shell leaves [0-9]+ untouched
grep [0-9]+ file.txt      # risky: if a matching filename exists, the shell expands it first