Sub-expressões são delimitadas por parênteses e podem ser aninhadas. Marcar parte de uma expressão como uma sub-expressão tem dois objetivos:
     Localizar um conjunto de alternativas. Por exemplo, a expressão
     cat(aract|erpillar|) corresponde a uma das três palavras: "cat",
     "cataract" ou "caterpillar". Sem os parênteses, corresponderia a
     "cataract", "erpillar" ou a uma string vazia.
    
Definir a sub-expressão como um grupo de captura (como definido acima). Quando toda a expressão tem correspondência, a parte da string de entrada que correspondeu à sub-expressão é passada de volta à função chamadora através do argumento ovector da função pcre_exec(). Parênteses de abertura são contados da esquerda para a direita (iniciando de 1) para obter os números dos grupos de captura.
   Por exemplo, se a string "the red king" é correspondida pela
   expressão
   the ((red|white) (king|queen))
   os grupos de captura são "red king", "red" e "king",
   e são numerados com 1, 2 e 3.
  
   O fato dos parênteses terem duas funções nem
   sempre ajuda. Frequentemente é necessária uma sub-expressão de
   agrupamento sem a necessidade de captura. Se um parêntese
   de abertura for seguido por "?:", a sub-expressão não
   faz nenhuma captura, e não é contado ao computar o
   número de sub-expressões de captura subsequentes. Por exemplo,
   se a string "the white queen" é correspondida pela
   expressão
   the ((?:red|white) (king|queen))
   as substrings capturadas são "white queen" e "queen", e
   são numeradas com 1 e 2. O número máximo de subtrings capturadas
   é 65535. Porém, pode não ser possível compilar expressões deste tamanho,
   dependendo das opções de configuração da biblioteca libpcre.
  
Como um atalho conveniente, se qualquer configuração de opção for necessária no início de uma sub-expressão sem captura, as letras de opções podem aparecer entre o "?" e o ":". Assim, as duas expressões
(?i:saturday|sunday) (?:(?i)saturday|sunday)
correspondem exatamente ao mesmo conjunto de strings. Como os ramos alternativos são testados da esquerda para a direita, e as opções não são redefinidas até que se alcance o final da sub-expressão, uma configuração de opção em um ramo não afeta ramos subsequentes, portanto as expressões acima correspondem a "SUNDAY" e também a "Saturday".
   É possível nomear uma sub-expressão usando a sintaxe
   (?P<nome>expressão). Esta sub-expressão será então
   indexada no array de correspondências pela sua posição numérica normal e
   também pelo nome. Há duas sintaxes alternativas:
   (?<nome>expressão) e (?'nome'expressão).
  
   Algumas vezes é necessário ter correspondências múltiplas, mas não ter
   sub-grupos alternados em uma expressão regular. Normalmente, cada um destes receberia
   seu próprio número de referência embora apenas um seria
   possivelmente correspondido. Para contornar isto, a sintaxe (?| permite
   ter números duplicados. Considere o caso abaixo, onde a expressão regular corresponde à
   string Sunday:
  
(?:(Sat)ur|(Sun))day
   Aqui, Sun é armazenado na referência 2, enquanto que
   a referência 1 está vazia. Corresponder Saturday gera
   a referência 1 para Sat enquanto que a referência 2
   não existirá. Modificar a expressão usando (?| corrige
   este problema:
  
(?|(Sat)ur|(Sun))day
   Usando esta expressão, tanto Sun quanto Sat
   seriam armazenadas na referência 1.
  
