Como dividir o campo 1 em linhas distintas, mas manter o campo 2 copiado para cada nova linha criada

5

Entrada:

Nota: 2 colunas separadas por uma guia, espaços regulares separando palavras na coluna 2.

1   the mouse is dead
2   hit the wall
3   winter lasts forever

Saída desejada:

1   the
1   mouse
1   is
1   dead
2   hit
2   the
2   wall
3   winter
3   lasts
3   forever

O awk é o caminho a percorrer para isso?

    
por Sébastien Clément 18.01.2018 / 18:37

4 respostas

12

Bem, o primeiro campo é $1 , NF contém o número de campos na linha, podemos acessar os campos com $i , em que i é uma variável, e os loops funcionam quase como em C. Então:

$ awk '{for (i = 2; i <= NF; i++) printf "%s\t%s\n", $1, $i} ' < blah
1       the
1       mouse
...

(Isso não diferencia entre espaço e tabulação como separador de campo.)

    
por 18.01.2018 / 18:45
5

Com o GNU sed :

sed -E 's/^((\S+\s+)\S+)\s+/&\n/;P;D'

É apenas mais feio com a sintaxe POSIX sed :

s='[[:space:]]\{1,\}' S='[^[:space:]]\{1,\}'
sed "s/^\(\($S$s\)$S\)$s/&\
/;P;D"
    
por 18.01.2018 / 23:28
2

outro estranho um:

~$>echo '1   the mouse is dead
2   hit the wall
3   winter lasts forever
' | awk 'BEGIN { RS="[[:space:]]+"; } /^[[:digit:]]+$/ {line=$1; next}; { print line "\t" $1; }'
1   the
1   mouse
1   is
1   dead
2   hit
2   the
2   wall
3   winter
3   lasts
3   forever

e colocado um pouco melhor ..

# split all parts into single word records.
BEGIN { RS="[[:space:]]+"; } 

# if the record is a number the save
/^[[:digit:]]+$/ { line=$1; next }; 
# else use last saved line number and this record to format output.
{ print line "\t" $1; }
    
por 18.01.2018 / 20:21
1

Você também pode usar a função split com o awk:

awk -F"\t" 'BEGIN { OFS="\t" } { cols=split($2,arr," "); for ( i=1; i<=cols; i++ ) { print $1,arr[i] }}'
    
por 19.01.2018 / 00:13