Guia de aula laboratorial

O guia da 3º aula prática está disponível online. Os tópicos abordados incluem conceitos relacionados com a utilização de expressões regulares.

O ficheiro extraccao-web.zip ( http://web.tagus.ist.utl.pt/~bruno.martins/materials/class-materials/labs-gti/extraccao-web/extraccao-web.zip ) inclui vários exemplos para os conceitos abordados nas aulas de laboratório referentes a extracção de informação.

Expressões Regulares

As expressões regulares são um método formal para especificar um padrão de texto. Através do uso de expressões regulares é extremamente fácil fazer comparações ou encontrar uma expressão numa dada cadeia de caracteres. Como tal, as expressões regulares podem ser uma ferramenta muito útil no desenvolvimento de procedimentos para extracção de dados a partir de recursos não estruturados (e.g. documentos de texto ou páginas Web).

A linguagem Java dispõe de mecanismos muito bons para o tratamento de expressões regulares no pacote java.util.regex. Para obter informações detalhadas, é aconselhável o estudo da documentação deste pacote ( http://java.sun.com/j2se/1.4.2/docs/api/java/util/regex/package-summary.html ).

As expressões regulares fazem uso de um conjunto de caracteres especiais. Alguns deles são apresentados de seguida.

  • O caracter "*" é um elemento quantificador usado para mapear qualquer cadeia de caracteres (dada pela expressão antecedente) zero ou mais vezes.
    • Por exemplo A*B faz match com qualquer cadeia que comece com 0 ou mais ocorrências de A e termine com B.
  • Os caracteres "[]" são usados para mapear elementos de conjuntos.
    • Por exemplo [abc]def faz match com qualquer cadeia de quatro caracteres com a primeira letra 'a,' 'b' ou 'c', e as letras seguintes "def".
  • O caracter "^" é usado para fazer exclusões.
    • Por exemplo [^abc]def faz match com qualquer cadeia de quatro caracteres cuja primeira letra NÃO seja 'a' nem 'b' nem 'c', sendo "def" o resto da cadeia.
  • O caracter "-" é usado para especificar intervalos.
    • Por exemplo [A-D]ef faz match com qualquer cadeia de três caracteres cuja primeira letra esteja entre A e D (A e D inclusive), sendo "ef" o resto da cadeia.
  • O caracter "." é usado para mapear qualquer caracter.
    • Por exemplo a. faz match com qualquer cadeia de dois caracteres cuja primeira letra seja 'a'
  • O caracter "\" é usado para mapear uma classe de caracteres pré-definidos. São eles:
    • \d : Um dígito,
    • \D : Algo que não seja um dígito,
    • \s : Um espaço em branco,
    • \S : Algo que não seja um espaço em branco,
    • \w : Qualquer letra, dígito ou underscore ( _ )
    • \W : Algo que não seja letra, dígito ou underscore
  • O caracter "?" é um elemento quantificador que é usado para mapear um caracter zero ou uma vez.
    • Por exemplo a? faz match com uma cadeia contendo zero ou um uma ocorrência de 'a'
  • O caracter "+" é um elemento quantificador que é usado para mapear qualquer cadeia de caracteres (dada pela expressão antecendente) uma ou mais vezes.
    • Por exemplo a+ faz match com uma cadeia contento uma ou mais ocorrências de 'a'

Relativamente à utilização de expressões regulares em Java, através do pacote java.util.regex, um objecto da classe Pattern contém a expressão regular a ser usada numa comparação, enquanto que um objecto da classe Matcher contém os métodos que validarão uma String, dada uma expressão regular. Segue-se um exemplo:

Pattern padrao = Pattern.compile("B*");
Matcher pesquisa = padrao.matcher("Bruno");
if (pesquisa.matches()) System.out.println("OK");
else System.out.println("Problema");

A classe Matcher contém ainda os métodos replaceFirst(String) e replaceAll(String), os quais permitem fazer substituições com base nos "matches" que foram efectuados sob a String de origem.

Para se testar o uso de expressões regulares, pode ser usada a ferramenta online "
Regular Expression Test Page" ( http://www.fileformat.info/tool/regex.htm ), ou a seguinte aplicação Java de exemplo:

import java.util.regex.*;

/**
* Classe Java que exemplifica a utilização de expressões regulares
*/
public class ExampleRegExp {

public static void main (String [] args) {
if (args.length != 2) {
System.err.println ("java ExampleRegExp regexp texto");
return;
}
Pattern p;
try {
p = Pattern.compile (args [0]);
} catch (PatternSyntaxException e) {
System.err.println ("Regex syntax error: " + e.getMessage ());
System.err.println ("Error description: " + e.getDescription ());
System.err.println ("Error index: " + e.getIndex ());
System.err.println ("Erroneous pattern: " + e.getPattern ());
return;
}
String s = cvtLineTerminators (args [1]);
Matcher m = p.matcher (s);
System.out.println ("Regex = " + args [0]);
System.out.println ("Text = " + s);
System.out.println ();
while (m.find ()) {
System.out.println ("Found " + m.group ());
System.out.println (" starting at index " + m.start () + " and ending at index " + m.end ());
System.out.println ();
}
}

// Tratamento dos caracteres \n e \r
static String cvtLineTerminators (String s) {
StringBuffer sb = new StringBuffer (80);
int oldindex = 0, newindex;
while ((newindex = s.indexOf ("\\n", oldindex)) != -1) {
sb.append (s.substring (oldindex, newindex));
oldindex = newindex + 2;
sb.append ('\n');
}
sb.append (s.substring (oldindex));
s = sb.toString ();
sb = new StringBuffer (80);
oldindex = 0;
while ((newindex = s.indexOf ("\\r", oldindex)) != -1) {
sb.append (s.substring (oldindex, newindex));
oldindex = newindex + 2;
sb.append ('\r');
}
sb.append (s.substring (oldindex));
return sb.toString ();
}
}

Links