Processing math: 0%

Table of Contents

SPLN

Diário de Bordo - Aula 2 - 2016-02-22

Sumário

Diário

Revisões

Para introduzir a aula, começamos por rever a script criada na semana anterior, que conta o número de palavras proveniente do STDIN.

Estruturas de dados em Perl

Declaração de lista (referência global à lista): @a Aceder ao elemento na posição i da lista a: $a[$i]

Declaração de array associativo (hash): %a Aceder ao valor da chave k da lista a: $a{$k}

Acesso ao conteúdo da posição dada pelas chaves k1 e k2 de um array associativo (hash) bidimensional: $a{$k1}{$k2}

''$&'' carácter especial de matching no Perl

Na aula exploramos as funcionalidades da variável `$&` como acesso aos tokens que compõem uma dada linha que queremos tratar.

  #!/usr/bin/perl
  
  while(/(\w+) (\w+)/) {
    print "$1 $2\n";
  }

No exemplo anterior acedemos aos tokens captados pela expressão dentro da condição do while, sendo 1 a sequência de carateres antes do espaço e 2 a sequência a seguir ao espaço.

Lei de Zipf

É uma lei empírica que rege à dimensão, importância ou frequência dos elementos de uma lista ordenada. Conclusões que retiramos na aula foram que existe uma relação entre o aumento de palavras comuns que surgem num determinado texto com a dimensão do mesmo.

Scripts

1. Contar o número de vezes que cada palavra se repete

  #!/usr/bin/perl
  
  use warnings;
  use strict;
  use utf8::all;
  
  my (%oco);
  my ($c);
  
  while (<>) {
  	next if /</; #salta linhas com "<"
    	while ($_ =~ /\w+/g) {
    		$oco{$&}++;
      }
  }
  foreach my $p (keys %oco){
    print "$p: $oco{$p}\n";
  }

2. Ordenação do output segundo as chaves de uma hash

  #!/usr/bin/perl
  
  use warnings;
  use strict;
  use utf8::all;
  
  my (%oco);
  my ($c);
  
  while (<>) {
  	next if /</; #salta linhas com "<"
    	while ($_ =~ /\w+/g) {
    		$oco{$&}++;
    }
  }
  #ordenar
  foreach my $p (sort keys %oco){
    print "$p: $oco{$p}\n";
  }

3. Apresentação do conteúdo da hash ordenado segundo o número de ocorrências de cada palavra

  #!/usr/bin/perl
  
  use warnings;
  use strict;
  use utf8::all;
  
  my (%oco);
  my ($c);
  
  while (<>) {
    next if /</; # salta linhas começadas por "<", poder-se-ia escrever "if (/^</){ next; }"
      while ($_ =~ /\w+/g) {
        $oco{$&}++;
    }
  }
  # critério de comparação de ocorrências (trocar ordem - trocar b com a)
  # $a e $b são definidos internamente pelo Perl quando definimos critérios de comparação,
  # pelo que se deve evitar declarar variáveis com esses nomes
  
  foreach my $p (sort{$oco{$a} <=> $oco{$b}} keys %oco){
    print "$p: $oco{$p}\n";
  }

4. Contar o número de vezes que cada palavra se repete, ordenando o output pelo número de ocorrências (decrescente)

  use warnings;
  use strict;
  use utf8::all;
  
  my (%oco);
  
  while (<>) {
    next if /^</; # ou if (/^</) {next;}
  
      while( /\w+/g ) {
        $oco{$&}++;
      }
  }
  
  foreach my $p (sort{ mycompare($a, $b) } keys %oco) {
    print "$p: $oco{$p}\n";
  }
  
  # Criação de uma função
  # Esta função é usada como critério de comparação no sort
  # No caso do número de ocorrências ser igual é feita ordenação alfabética
  # com recurso à função cmp
  sub mycompare {my ($a, $b)=@_; # lista do costume: @_
    if ($oco{$a} < $oco{$b}) {return 1}
    if ($oco{$a} > $oco{$b}) {return -1}
    return $a cmp $b;
  }

Numa seguinte script fizemos uma optimização, de modo a contabilizar palavras com hífen ('-') como uma única palavra. (e.g. deu-lhe, avisou-o)

Dentro do ciclo while a expressão regular passa a ser: /\w+(-\w+)*/g

5. “Calculadora de Tabela de Capitalização Preferencial”, ctcp.pl

  #!/usr/bin/perl
  
  use warnings;
  use strict;
  use utf8::all;
  use Data::Dumper; # Este módulo permite o print imediato de estruturas de dados
  
  my (%oco);
  my ($c);
  my $pm = qr{[[:upper:]]\w+}; # qr{..} - tudo o que vem dentro de chavetas é tratado como expressão regular
  
  my $prep = qr{d[eoa]s?};
  my $np = qr{$pm( ($prep )?$pm)*};
  
  while (<>) {
    next if /^</;
    $_ =~ s/^\w+(-\w+)*//;
    while( /\w+(-\w+)*/g ) {
    	$oco{lc($&)}{$&}++;
    }
  }
  
  print Dumper(\%oco);
  
  # Quando em Perl queremos que o texto não seja processado podemos usar a marca __END__
  __END__
   Tudo o que se coloca abaixo de '__END__' é considerado documentação, logo,
  mesmo que seja colocado código em perl ele não será interpretado como tal

Neste script estuda-se para uma dada palavra o número de ocorrências dessa mesma palavra com capitalizações diferentes. Correndo o comando 'perl ctcp.pl cetemGordo.txt > out.txt' obtemos no ficheiro out.txt o seguite:

  'universidades' => {
                 'universidades' => 31,
                 'Universidades' => 5
  'anti-sida' => {
             'anti-sida' => 2
  'livros-sida' => {
    (...)
  'luminosidade' => {
                'luminosidade' => 1
  'curiosidades' => {
                'curiosidades' => 2
  'diversidade' => {
               'Diversidade' => 1,
               'diversidade' => 11
  'subsidariedade' => {
                  'Subsidariedade' => 1,
                  'subsidariedade' => 2