Sei que isso pode ser óbvio para a maioria das pessoas que usam RegEx com frequência, mas no caso de algum leitor ser novo no RegEx, achei que deveria apontar uma observação que fiz que foi útil para um de meus projetos.
Em uma resposta anterior de @kennytm:
^\d{5}(?:[-\s]\d{4})?$
…? = O padrão antes dele é opcional (para condição 1)
Se você deseja permitir códigos postais padrão de 5 dígitos e +4, este é um ótimo exemplo.
Para corresponder apenas aos códigos postais no formato 'Zip + 4' dos EUA, conforme eu precisava fazer (apenas as condições 2 e 3), basta remover o último ?
para que ele sempre corresponda ao último grupo de 5 caracteres.
Uma ferramenta útil que recomendo para mexer com RegEx está no link abaixo:
https://regexr.com/
Eu uso essa ferramenta com frequência quando encontro o RegEx que faz algo semelhante ao que eu preciso, mas poderia ser um pouco melhor adaptado. Ele também possui um menu de referência RegEx bacana e uma interface informativa que o mantém ciente de como suas alterações afetam as correspondências para o texto de amostra inserido.
Se eu errar ou perder uma informação importante, corrija-me.
\d{5}([ \-]\d{4})?
.