Ajuste o espaço entre 2 colunas para fazê-las parecerem retas

3

file1.txt :

hi
wonderful
amazing
sorry
superman
superhumanwith
loss

file2.txt :

1
2
3
4
5
6
7

Quando tento combinar usando colar -d "" file1.txt file2.txt > actualout.txt

actualout.txt :

hi 1
wonderful 2
amazing 3
sorry 4
superman 5
superhumanwith 6
loss 7

Mas eu quero que minha saída fique assim desejado

OUT.txt :

hi             1
wonderful      2
amazing        3 
sorry          4
superman       5 
superhumanwith 6
loss           7

Qual comando pode ser usado para combinar 2 arquivos com a aparência desejada? Solaris 5.10 ksh nawk, sed, colar

    
por ayrton_senna 12.06.2015 / 01:53

5 respostas

2
awk 'FNR==1{f+=1;w++;}
     f==1{if(length>w) w=length; next;}
     f==2{printf("%-"w"s",$0); getline<f2; print;}
    ' f2=file2 file1 file1

Nota: file1 é intencionalmente lido duas vezes; a primeira vez é encontrar o comprimento máximo da linha, e a segunda vez é formatar cada linha para a concatenação final com as linhas correspondentes do arquivo2. - file2 é lido de forma programática; seu nome é fornecido pelo recurso variável-as-an-arg do awk.

Saída:

hi             1
wonderful      2
amazing        3
sorry          4
superman       5
superhumanwith 6
loss           7

Para manipular qualquer número de arquivos de entrada, os seguintes trabalhos: mas * Nota: ele não suporta a repetição do mesmo nome de arquivo. ou seja, cada nome do arquivo arg se refere a um arquivo diferente. Pode, no entanto, lidar com arquivos de diferentes comprimentos - além de um arquivo EOF, espaços são usados.

awk 'BEGIN{ for(i=1; i<ARGC; i++) { 
              while( (getline<ARGV[i])>0) { 
                 nl[i]++; if(length>w[i]) w[i]=length; }
              w[i]++; close(ARGV[i])
              if(nl[i]>nr) nr=nl[i]; }
            for(r=1; r<=nr; r++) {
              for(f=1; f<ARGC; f++) {
                if(r<=nl[f]) getline<ARGV[f]; else $0=""  
                printf("%-"w[f]"s",$0); } 
              print "" } }
    ' file1 file2 file3 file4

Aqui está a saída com 4 arquivos de entrada:

hi             1 cat   A 
wonderful      2 hat   B 
amazing        3 mat   C 
sorry          4 moose D 
superman       5       E 
superhumanwith 6       F 
loss           7       G 
                       H 
    
por 12.06.2015 / 10:27
7

Você parece precisar de column :

paste file1.txt file2.txt | column -tc2

que cria esta saída:

hi              1
wonderful       2
amazing         3
sorry           4
superman        5
superhumanwith  6
loss            7


Você pode também escrever seu próprio script para fazer a formatação. Aqui está uma maneira de usar awk :

awk '
  NR==FNR { a[FNR] = $0 ; if (length > max) max = length ; next }
  { printf "%-*s  %s\n", max, a[FNR], $0 }
' file1.txt file2.txt
    
por 12.06.2015 / 07:06
4

pr

Eu provavelmente usaria pr :

printf %s\n hi wonderful amazing sorry  \
             superman superhumanwith loss >/tmp/file
#^what is all of that, anyway?^

seq 7 | pr -tm /tmp/file -

pr can -m erge arquivos de entrada (aqui /tmp/file e - stdin) linha por linha como paste em coluna, mas pode levar > muitos outros parâmetros além. Por padrão, ele também imprime cabeçalhos e rodapés, mas -t esmaga isso.

OUTPUT:

hi                      1
wonderful               2
amazing                 3
sorry                   4
superman                5
superhumanwith          6
loss                    7

expand

Se você estiver interessado em se tornar mais específico, outra opção é expand - porque você pode entregar uma lista de paradas de tabulação virtuais que serão expandidas para tantos espaços como necessário para preenchê-los.

seq 7 | paste /tmp/file - | expand -t15

Aqui só precisamos do primeiro -t abstop, claro ...

hi             1
wonderful      2
amazing        3
sorry          4
superman       5
superhumanwith 6
loss           7

... mas se mais fosse desejado ...

seq 14 | paste /tmp/file - /tmp/file - | expand -t15,23,38,46

... podemos soletrá-los em uma lista composta e separada por vírgulas ...

hi             1       hi             2
wonderful      3       wonderful      4
amazing        5       amazing        6
sorry          7       sorry          8
superman       9       superman       10
superhumanwith 11      superhumanwith 12
loss           13      loss           14

grep :

Para encontrar o comprimento da linha mais longa em um arquivo, e sem contar os espaços à direita, e conforme incrementado pelas posições padrão das paradas de tabulação de 8 caracteres, isso provavelmente funcionará:

i=0
while grep -Eq ".{$(((i+=8)-1))}.*[^[:blank:]]" <infile; do :; done

Esse loop aumentará $i por 8 para cada execução e pesquisará <infile para qualquer linha que contenha pelo menos tantos caracteres quanto forem contados em $i seguido por qualquer caractere não em branco . E assim, quando grep não encontrar essa linha, ela retornará false e, para seus dados de exemplo, ela será atribuída:

echo "$i"
16

wc :

Mas essas são todas as soluções POSIX. O mais simples de fazer em um sistema GNU é:

wc -L <infile

... para listar o comprimento da linha mais longa em <infile , mas isso incluirá contagens de espaços em branco à direita.

    
por 12.06.2015 / 11:05
3

Se você insistir em fazer isso com awk :

awk -v file=file2.txt '{
        cnt++
        a[cnt] = $0
        getline b[cnt] <file
        if(length(a[cnt]) > max)
            max = length(a[cnt])
    }
    END {
        max++
        for(i = 1; i <= cnt; i++)
            printf "%-" max "s%s\n", a[i], b[i]
    }' file1.txt

Em uma nota lateral: eu tenho certeza que esta roda em particular foi reinventada um zilhão de vezes, mas agora eu prefiro não coagir meu cérebro a inventar o encantamento certo para encontrar exemplos adequados de SE / SO art. :)

    
por 12.06.2015 / 06:36
1

Bem, eu encontrei o que eu queria. Isso funciona no Solaris 5.10.

paste file1 file2| pr -t -e$(awk 'n<length {n=length} END {print n+1}' file1)

Estou armazenando o comprimento da string mais longa no primeiro arquivo e usando-o para delimitar por tabulação

Cenário de vários arquivos

Desde que saibamos qual arquivo terá a palavra mais longa, eu substituiria esse nome de arquivo no cálculo do tamanho e usaria o colar para unir vários arquivos. Se file4.txt tiver a string mais longa. Então solução seria

paste file1 file2 file3 file4 | pr -t -e$(awk 'n<length {n=length} END {print n+1}' file4)

    
por 12.06.2015 / 21:57