I want to match a phone number that can have letters and an optional hyphen:
333-WELL
4URGENT
Supposing that you want to allow the hyphen to be anywhere, lookarounds will be of use to you. Something like this:
^([A-Z0-9]{7}|(?=^[^-]+-[^-]+$)[A-Z0-9-]{8})$
There are two main parts to this pattern: [A-Z0-9]{7}
to match a hyphen-free string and (?=^[^-]+-[^-]+$)[A-Z0-9-]{8}
to match a hyphenated string.
The (?=^[^-]+-[^-]+$)
will match for any string with a SINGLE hyphen in it (and the hyphen isn't the first or last character), then the [A-Z0-9-]{8}
part will count the characters and make sure they are all valid.