Extrair informações de um texto usando expressão regular

Boa tarde pessoal.

Eu estou desenvolvendo uma expressão regular para extrair informações de um texto. Eu quero obter apenas um parágrafo. O padrão do texto que estou extraindo é: ele sempre inicia com “Processo XXX” e “termina com uma data”.

A expressão regular que estou usando é a seguinte:
Processo\s\d{3,3}.*(\n.*)*\d{2,2}\/\d{2,2}\/\d{4,4}

O problema é que ela termina no último bloco. Eu gostaria de obter apenas o parágrafo completo.

Exemplo de um texto a ser extraído:

Processo 001
Incluído
em pauta para 01/03/2016, às 08:30. Ficam cientes
os advogados de que a intimação do acórdão
dar-se-á na própria sessão de julgamento, nos termos
do art 47 do regimento Interno da Turma Recursal.
02/03/2015
Processo 001
Incluído em pauta para 01/03/2016, às 08:30. Ficam
cientes os advogados de que a intimação do acórdão
dar-se-á na própria sessão de julgamento, nos termos
do art 47 do regimento Interno da Turma Recursal.
02/03/2015

Ao executar a expressão neste texto, tudo é selecionado.

Fiz alguns testes e cheguei a isso:

Processo.+?((?=\\n?Processo)|(?>\\d{4}$))

Em Java eu compilei esse pattern com a flag Pattern.DOTALL, assim:

String regex = "Processo.+?((?=\\n?Processo)|(?>\\d{4}$))";
Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);

Normalmente .+ não reconhece caracteres de nova linha e afins, mas quando você usa esta flag o “.” passa a reconhecer TUDO.

Como funciona

A parte Processo.+? é uma versão modificada de Processo.+. Imagine que você tem o seguinte texto:

Processo abc X Processo abc X

E a seguinte expressão:

Processo.+X

O resultado será desde a palavra “Processo” até a última ocorrência de “X”. Mas se acrescentarmos o ‘?’ (assim: Processo.+?X), o resultado será apenas até a primeira ocorrência de “X”. Ou seja:

Processo.+X       Processo abc X Processo abc X
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Processo.+?X      Processo abc X Processo abc X
                  ^^^^^^^^^^^^^^

Faça o teste:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    static Matcher result1, result2;

    public static void main(String[] args) {
        String text = "Processo abc X Processo abc X";

        result1 = Pattern.compile("Processo.+X").matcher(text);
        result2 = Pattern.compile("Processo.+?X").matcher(text);

        result1.find();
        result2.find();

        System.out.println(result1.group());
        System.out.println(result2.group());
    }
}

Em seguida nós temos a expressão (?=\\n?Processo) que significa:

Até encontrar a palavra “Processo” (precedida por 0 ou 1 nova linha), mas sem incluí-la no resultado.

Isto já é o suficiente para conseguirmos extrair desde o primeiro até o penúltimo paragrafo do seu texto, mas ele falha por não conseguir retornar o último paragrafo (pois o último não é sucedido por mais nenhuma palavra).

Por isso temos a próxima expressão (?>\\d{4}$), que significa:

Até o final do texto, desde que o texto termine com 4 digitos consecutivos.

Em resumo, eu quero tudo, desde uma palavra “Processo” até o início de outra palavra “Processo” OU até o final do texto desde que termine com 4 digitos!

Por isso eu fiz assim ((?=\\n?Processo)|(?>\\d{4}$)) o ‘|’ representa o “OU” da frase acima.

Você poderia ser mais específico e substituir (?>\\d{4}$) por (?>\\d{2}/\\d{2}/\\d{4}$), fica a seu critério.

Bom, não sei se tem certeza de que o texto sempre será formatado da forma como mostrou ou se ele pode variar, de qualquer forma imaginei que não temos controle sobre a formatação dele, logo, tal texto poderia ser servido com cada processo em sua própria linha, assim:

Processo 001 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015
Processo 002 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015

Ou tudo numa linha só:

Processo 001 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015 Processo 002 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015

De qualquer forma a expressão que apresentei lida bem com essas situações.

Para essa resposta eu usei como referência a documentação das seguintes classes do Java:

Pattern
Matcher

E também me baseei bastante nesta resposta do Stackoverflow.

E usei este código para realizar os testes:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {
    static private String regex = "Processo.+?((?=\\n?Processo)|(?>\\d{4}$))";

    static private String originalText =
          "Processo 001\n"
        + "Incluido\n"
        + "em pauta para 01/03/2016, às 08:30. Ficam cientes\n"
        + "os advogados de que a intimação do acórdão\n"
        + "dar-se-á na própria sessão de julgamento, nos termos\n"
        + "do art 47 do regimento Interno da Turma Recursal.\n"
        + "02/03/2016\n"
        + "Processo 002\n"
        + "Incluído em pauta para 01/03/2016, às 08:30. Ficam\n"
        + "cientes os advogados de que a intimação do acórdão\n"
        + "dar-se-á na própria sessão de julgamento, nos termos\n"
        + "do art 47 do regimento Interno da Turma Recursal.\n"
        + "02/03/2015";

    static private String eachProcessInOwnLine =
          "Processo 001 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015"
        + "Processo 002 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2016";

    static private String allInOneLine = "Processo 001 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015 Processo 002 Incluído em pauta para 01/03/2016, às 08:30. Ficam cientes os advogados de que a intimação do acórdão dar-se-á na própria sessão de julgamento, nos termos do art 47 do regimento Interno da Turma Recursal. 02/03/2015";

    private static void printMatches(Matcher matcher) {
        for (int count = 1; matcher.find(); count++) {
            System.out.println("PARÁGRAFO EXTRAÍDO >>> " + count);
            System.out.println(matcher.group());
            System.out.println();
        }
    }

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);

        System.out.println("### Imprimindo resultado com o texto original");
        printMatches(pattern.matcher(originalText));

        System.out.println("### Imprimindo resultado com o texto onde cada processo tem sua própria linha");
        printMatches(pattern.matcher(eachProcessInOwnLine));

        System.out.println("### Imprimindo resultado onde o texto reúne toda informação em apenas uma linha");
        printMatches(pattern.matcher(allInOneLine));
    }
}
1 curtida

Eu testei a sua expressão no site: http://www.piazinho.com.br/ed3/exemplos.html#1

porém a expressão (?>\d{4}$) não está funcionando, ela não está reconhecendo o sinal de >.
Você saberia fazer uma alternativa para substituir o > por um caracter que funcione neste site?

No notepad++ ela funcionou perfeitamente.

Acessei o site, bem legal.

Colei o texto que você forneceu no primeiro post e testei com a seguinte expressão:

Processo[\W\w]+?(?:\d{4}$)

Substitui o > por : e parece que funcionou.

1 curtida