Terminal Unix - Como imprimir cada bigrama / trigrama de uma linha?

2

Como posso imprimir cada bigrama de uma linha usando o terminal unix? Símbolos de pontuação são considerados como 'palavra'.

Por exemplo, se eu precisar seguir a entrada:

This is ! line .

This is ! second line .

Minha saída deve ser a seguinte, se estiver procurando por cada bigrama:

This is
is !
! line
line .

This is
is !
! second
second line
line .

Minha saída deve ser a seguinte, se estiver procurando por cada trigam:

This is !
is ! line
! line .

this is !
is ! second
! second line
second line .

Fiz o meu melhor para descobrir como conseguir isso, mas estou preso. Espero que alguém possa me ajudar!

EDITAR:

O comando

grep -Eio '[a-z!.]+ [a-z!.]+'

Retorna

This is
! line
This is
! second
line .

O que chega perto, mas ainda não é o que eu preciso.

    
por Thijmen Dam 08.12.2017 / 11:51

3 respostas

4

Você precisaria de uma implementação de grep que não apenas pudesse imprimir partes das linhas (como seu grep com sua opção -o para imprimir somente o que corresponde à linha onde há uma correspondência), mas também partes das linhas várias vezes .

pcregrep é um deles:

pcregrep -o1 -o2 --om-separator=' ' '(\S+)\s*(?=(\S+))'

Aqui, -o2 imprime algo que não corresponde por si só, algo que é correspondido apenas a um operador antecipado ( (?=...) ), por isso pcregrep continuará a procurar mais correspondências a partir do final da palavra saída por -o1 .

\s corresponde aos caracteres de espaçamento (vertical ou horizontal), portanto, palavras nesse caso são sequências de caracteres sem espaçamento.

Em vez disso, você pode usar awk :

awk '{for (i=1; i<NF; i++) print $i, $(i+1)}'

Para awk , palavras são seqüências de caracteres não vazios (espaçamento horizontal), em algumas implementações limitadas a SPC e TAB.

Se você quiser considerar line. como duas palavras separadas: line e . , você pode usar a implementação GNU de awk que suporta a definição de campos com base em padrões como:

gawk -v FPAT='[[:alnum:]]+|[[:punct:]]+' '{for (i=1; i<NF; i++) print $i, $(i+1)}'

Onde palavras são definidas como sequências de caracteres alfanuméricos ou sequências de caracteres de pontuação.

    
por 08.12.2017 / 12:01
3

Você pode usar o perl assim

bigrama

perl -lne 'while(/(\S+\s+\S*){1}/){print $&;s/\S+\s+//}' file

This is
is !
! line
line .
This is
is !
! second
second line
line .

trigrama

perl -lne 'while(/(\S+\s+\S*){2}/){print $&;s/\S+\s+//}' file

This is !
is ! line
! line .
This is !
is ! second
! second line
second line .

Altere o número nas chaves para quantos você quiser por linha (-1).

    
por 08.12.2017 / 13:16
2

Desculpe, este uso , não :

para bigrama :

sed 'h;:a;s/^ *\([^ ]\+\) \+\([^ ]\+\).*$/ /p;g;s/^ *[^ ]\+//;h;ta;'

ou talvez (substituindo \+ por \{1,\} como o comentário de Stéphane Chazelas apontou :

sed -e 'h;:a' -e 's/^ *\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\).*$/ /p;g;s/^ *[^ ]\{1,\}//;h;ta'

e para trigrama :

sed 'h;:a;s/^ *\([^ ]\+\) \+\([^ ]\+\) \+\([^ ]\+\).*$/  /p;g;s/^ *[^ ]\+//;h;ta;'

Para o sed do Mac:

sed -e 'h;:a' -e 's/^ *\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\).*$/  /p;g;s/^ *[^ ]\{1,\}//;h;ta'

Explicado:

Bigram como um script sed:

#!/bin/sed -f

    h;                                       # Hold pattern space to hold space
:a;                                          # label for branch
    s/^ *\([^ ]\+\) \+\([^ ]\+\).*$/ /p; # print 1st bigram
    g;                                       # restore from hold space
    s/^ *[^ ]\+//;                           # drop 1st monogram
    h;                                       # hold pattern space
    ta;                                      # branch if last search success

onde última t (ramificação condicional) para rotular :a apenas se a última s/// corresponder.

E a versão do Mac em sed do bigram.sed:

#!/usr/bin/sed -f

    h;                                    # Hold pattern space to hold space
                                          # label for branch
:a
    s/^ *\([^ ]\{1,\}\) \{1,\}\([^ ]\{1,\}\).*$/ /p; # print 1st bigram
    g;                                    # restore from hold space
    s/^ *[^ ]\{1,\}//;                    # drop 1st monogram
    h;                                    # hold pattern space
                                          # branch if last search success
    ta
    
por 08.12.2017 / 12:19