−Table of Contents
SPLN
Diário de Bordo - Aula 2 - 2016-02-22
Sumário
- Revisões da aula anterior;
- Estruturas de dados em Perl: arrays, arrays associativos (hashes);
- Elemento de matching no perl (
$1
…,$&
); - Lei de Zipf;
- Scripts para análise do ficheiro cetemGordo.txt:
- Contar ocorrências de palavras (script_1.pl);
- Ordenar palavras;
- Critério de comparação de ocorrências;
- Funções em perl;
- Calculadora de Tabela de Capitalização Preferencial“, ctcp.pl;
- Registo e Visita guiada ao GitLab;
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