Que comando (s) alimentará um arquivo de texto delimitado por tabulações e cortará cada linha em 80 caracteres?

8

Eu tenho arquivos de texto com várias linhas de dados (às vezes) delimitados por tabulação. Eu gostaria de enviar o arquivo para que eu possa ver - então eu gostaria de ver apenas os primeiros 80 caracteres de cada linha (eu projetei o arquivo de texto para colocar as coisas importantes primeiro em cada linha).

Eu pensei que poderia usar o cat para ler cada linha do arquivo e enviar cada linha para o próximo comando em um canal:

cat tabfile | cut -c -80

Mas isso parecia quebrado. Eu tentei monkeying ao redor, e grep apareceu para trabalhar - mas depois eu descobri que, não, não (não cada linha no arquivo tinha 80 + caracteres) - parece guias são contados como caracteres únicos por corte.

Eu tentei:

cat tabfile | tr \t 0 | cut -c -80

Mesmo assim, isso reduziria um pouco meus dados, eliminando a legibilidade do espaço em branco. Mas isso não funcionou. Nem fez:

cat tabfile | tr 1 0 | cut -c -80

Talvez eu esteja usando errado? Eu tive problemas com tr antes, querendo remover vários espaços (aparece a versão do tr que eu tenho acesso a esta máquina tem uma opção -s para espremer vários caracteres - talvez eu precise jogar com ele mais)

Tenho certeza de que, se eu mexesse, poderia usar perl, awk ou sed, ou algo para fazer isso.

No entanto, eu gostaria de uma solução que usa comandos regulares (POSIX?), para que seja o mais portátil possível. Se eu acabar usando o tr, eu provavelmente tentaria virar as abas em caracteres, talvez fazer um cálculo, cortar o cálculo e depois transformar esses caracteres de volta em abas para a saída.

Ele não precisa ser uma única linha / inserido diretamente na linha de comando - um script é bom.

Mais informações em arquivos de guia:

Eu uso a tabulação para quebrar campos, porque algum dia eu posso querer importar dados para algum outro programa. Então, eu costumo ter apenas uma aba entre as partes do conteúdo. Mas também uso guias para alinhar as coisas com colunas verticais, para ajudar na legibilidade ao examinar o arquivo de texto simples. O que significa que para algumas partes do texto eu coloco o final do conteúdo com espaços até chegar onde a guia irá trabalhar alinhando o próximo campo com os que estão acima e abaixo dele.

DarkTurquoise           #00CED1         Seas, Skies, Rowboats   Nature
MediumSpringGreen       #00FA9A         Useful for trees        Magic  
Lime                    #00FF00         Only for use on spring chickens and fru$
    
por user3082 25.12.2014 / 08:56

5 respostas

9

Acho que você está procurando expand e / ou unexpand . Parece que você está tentando garantir que uma largura de \t ab seja contada como 8 caracteres em vez de um único. fold fará isso também, mas irá envolver sua entrada na próxima linha em vez de truncá-la. Eu acho que você quer:

expand < input | cut -c -80

expand e unexpand são POSIX especificado :

  • O utilitário expand deve gravar arquivos ou a entrada padrão na saída padrão com caracteres \t ab substituídos por um ou mais caracteres espaço necessários para preencher a próxima parada da tabulação. Quaisquer caracteres backspace devem ser copiados para a saída e fazer com que a contagem de posição da coluna para cálculos de tabulação seja diminuída; a contagem da posição da coluna não deve ser decrementada abaixo de zero.

Muito simples. Então, aqui está uma olhada no que isso faz:

unset c i; set --;                                                             
until [ "$((i+=1))" -gt 10 ]; do set -- "$@" "$i" "$i"; done                      
for c in 'tr \t \ ' expand;  do eval '                                           
    { printf "%*s\t" "$@"; echo; } | 
      tee /dev/fd/2 |'"$c"'| { 
      tee /dev/fd/3 | wc -c >&2; } 3>&1 |
      tee /dev/fd/2 | cut -c -80'
done

O loop until no topo recebe um conjunto de dados como ...

1 1 2 2 3 3 ...

É printf s com o sinalizador de preenchimento %*s arg, portanto, para cada um deles no conjunto printf será preenchido com tantos espaços quanto o número do argumento. Para cada um, ele acrescenta um caractere \t ab.

Todos os tee s são usados para mostrar os efeitos de cada filtro à medida que são aplicados.

E os efeitos são estes:

1        2        3        4        5        6        7        8                9               10
1  2   3    4     5      6       7        8         9         10 
1  2   3    4     5      6       7        8         9         10 
66
1        2        3        4        5        6        7        8                9               10
1        2        3        4        5        6        7        8                9               10 
1        2        3        4        5        6        7        8                
105

Essas linhas estão alinhadas em dois conjuntos como ...

  1. saída de printf ...; echo
  2. saída de tr ... ou expand
  3. saída de cut
  4. saída de wc

As quatro primeiras linhas são os resultados do filtro tr - em que cada \t ab é convertido em um único espaço .

E a parte inferior quatro, os resultados da corrente expand .

    
por 25.12.2014 / 14:38
3

Como as guias são mais para alinhamento do que para delimitação, uma maneira pode ser usar column e, em seguida, cut :

column -s '\t' -t <some-file | cut -c -80

Parece que column não é POSIX. Faz parte dos utilitários do BSD no Ubuntu, então eu suponho que seja uma plataforma cruzada.

    
por 25.12.2014 / 09:21
1

A sugestão de Don nos comentários foi um bom começo.

Isso é o que eu precisava para fazer (principalmente) funcionar:

pr +1 -1 -t -m -l1000 -w 80 tabfile

O -m foi necessário para que o sinalizador -w tenha efeito em uma única coluna. A man page poderia usar alguma reescrita para indicar isso.

Ao tentar uma solução alternativa, descobri que pr outputs \t caracteres, portanto, alimentar seus resultados para cut resultou no mesmo problema.

-1 (o sinalizador de coluna) diz especificamente na página man:

This option should not be used with -m.

No entanto, sem essa opção, pr trunca as linhas de maneira aleatória, com um comprimento muito menor que o especificado.

pr também insere um espaço antes (ou depois?) de cada palavra em um campo (ou seja, todo lugar em que tenho um único espaço, tem dois após o processamento). Se houver muitas palavras, os espaços inseridos ignorarão a restrição -w (criação de contorno). Mas, curiosamente, as "colunas", que não são delimitadas por tabulações (isto é, espaços em branco organizados), permanecem alinhadas.

    
por 25.12.2014 / 11:16
0

Usando awk :

awk '{ $0 = substr($0, 1, 80) }1' file

Baseado na resposta de Chris Down aqui .

    
por 25.12.2014 / 09:36
0

Um utilitário que deve ser verdadeiramente sensível à exibição é fold : infelizmente, parece não ter uma opção para descartar em vez de quebrar. Embora seja provavelmente ineficiente, você pode fazer algo como

while read -r line; do fold -w80 <<< "$line" | head -n1; done < file
    
por 25.12.2014 / 14:20