linux how unix-cabeça E cauda do arquivo



shell script basic commands (16)

O problema aqui é que programas orientados a fluxo não conhecem o tamanho do arquivo antecipadamente (porque pode não haver um, se for um fluxo real).

ferramentas como tail buffer as últimas n linhas vistas e aguardar o final do fluxo, em seguida, imprimir.

Se você quiser fazer isso em um único comando (e fazê-lo funcionar com qualquer deslocamento, e não repetir as linhas se elas se sobrepuserem), será necessário imitar esse comportamento que mencionei.

tente este awk:

awk -v offset=10 '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' yourfile

Digamos que você tenha um arquivo txt, qual é o comando para visualizar as 10 linhas principais e as 10 linhas inferiores do arquivo simultaneamente?

ou seja, se o arquivo tiver 200 linhas, visualize as linhas 1-10 e 190-200 de uma só vez.


Answer #1
(sed -u 10q; echo ...; tail) < file.txt

Apenas outra variação do tema (head;tail) , mas evitando o problema inicial de preenchimento do buffer para arquivos pequenos.



Answer #3

desenho em idéias acima (testado bash & zsh)

mas usando um apelido 'hat' Head and Tails

alias hat='(head -5 && echo "^^^------vvv" && tail -5) < '


hat large.sql

Answer #4

Com base no que @Samus_ explicou here sobre como o comando de @Aleksandra Zalcman funciona, essa variação é útil quando você não consegue identificar rapidamente onde a cauda começa sem contar as linhas.

{ head; echo "####################\n...\n####################"; tail; } < file.txt

Ou se você começar a trabalhar com algo diferente de 20 linhas, uma contagem de linhas pode até ajudar.

{ head -n 18; tail -n 14; } < file.txt | cat -n

Answer #5

Bem, você sempre pode encadeá-los juntos. Assim, head fiename_foo && tail filename_foo . Se isso não for suficiente, você pode escrever uma função bash em seu arquivo .profile ou em qualquer arquivo de login usado:

head_and_tail() {
    head $1 && tail $1
}

E, mais tarde, invoque-o no prompt do shell: head_and_tail filename_foo .


Answer #6

ed é o standard text editor

$ echo -e '1+10,$-10d\n%p' | ed -s file.txt

Answer #7
sed -n "1,10p; $(( $(wc -l ${aFile} | grep -oE "^[[:digit:]]+")-9 )),\$p" "${aFile}"

NOTA : A variável aFile contém o caminho completo do arquivo.


Answer #8

head -10 file.txt; tail -10 file.txt

Fora isso, você precisará escrever seu próprio programa / script.


Answer #9

Primeiras 10 linhas de arquivo.ext, depois as últimas 10 linhas:

cat file.ext | head -10 && cat file.ext | tail -10

As últimas 10 linhas do arquivo, depois as 10 primeiras:

cat file.ext | tail -10 && cat file.ext | head -10

Você pode então canalizar a saída em outro lugar também:

(cat file.ext | head -10 && cat file.ext | tail -10 ) | your_program


Answer #10

Você pode simplesmente:

(head; tail) < file.txt

E se você precisar usar pipes por alguma razão, então:

cat file.txt | (head; tail)

Nota: imprimirá linhas duplicadas se o número de linhas no arquivo.txt for menor que as linhas padrão da cabeça + linhas de cauda padrão.


Answer #11

Demorou muito tempo para acabar com esta solução que, parece ser a única que cobriu todos os casos de uso (até agora):

command | tee full.log | stdbuf -i0 -o0 -e0 awk -v offset=${MAX_LINES:-200} \
          '{
               if (NR <= offset) print;
               else {
                   a[NR] = $0;
                   delete a[NR-offset];
                   printf "." > "/dev/stderr"
                   }
           }
           END {
             print "" > "/dev/stderr";
             for(i=NR-offset+1 > offset ? NR-offset+1: offset+1 ;i<=NR;i++)
             { print a[i]}
           }'

Lista de recursos:

  • saída ao vivo para a cabeça (obviamente que para a cauda não é possível)
  • nenhum uso de arquivos externos
  • barra de progresso um ponto para cada linha após o MAX_LINES, muito útil para tarefas de longa duração.
  • barra de progresso no stderr, assegurando que os pontos de progresso são separados da cabeça + cauda (muito útil se você quiser canalizar stdout)
  • evita possível ordem de log incorreta devido ao buffering (stdbuf)
  • evite duplicar a saída quando o número total de linhas for menor que head + tail.

Answer #12

Para imprimir as primeiras 10 e últimas 10 linhas de um arquivo, você pode tentar isto:

cat <(head -n10 file.txt) <(tail -n10 file.txt) | less


Answer #13

Para lidar com pipes (fluxos) e arquivos, adicione isso ao seu arquivo .bashrc ou .profile:

headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' ; }

Então você pode não só

headtail 10 < file.txt

mas também

a.out | headtail 10

(Isso ainda acrescenta linhas em branco espúrias quando 10 excede o comprimento da entrada, ao contrário do antigo simples a.out | (head; tail) . Obrigado, respondentes anteriores.)

Nota: headtail 10 , não headtail -10 .


Answer #14

Eu diria que, dependendo do tamanho do arquivo, ler ativamente em seu conteúdo pode não ser desejável. Nessa circunstância, acho que alguns scripts simples de shell devem ser suficientes.

Veja como eu lidei com isso recentemente para vários arquivos CSV muito grandes que estava analisando:

$ for file in *.csv; do echo "### ${file}" && head ${file} && echo ... && tail ${file} && echo; done

Isso imprime as primeiras 10 linhas e as últimas 10 linhas de cada arquivo, além de imprimir o nome do arquivo e algumas reticências antes e depois.

Para um único arquivo grande, você poderia simplesmente executar o seguinte para o mesmo efeito:

$ head somefile.csv && echo ... && tail somefile.csv

Answer #15

Por que não usar sed para essa tarefa?

sed -n -e 1,+9p -e 190,+9p textfile.txt





scripting