obtém uma porcentagem de um arquivo

3

Existe um comando linux para retornar o último x% de um arquivo? Eu sei que tail pode retornar um número de linhas (-n) ou número de bytes (-c), mas e se eu quisesse obter os últimos 25% de um arquivo? Existe um comando para fazer isso?

    
por raphael75 05.01.2018 / 20:09

3 respostas

13

A divisão do GNU pode fazer praticamente o que você pede; dado um arquivo de texto in.txt , isso imprimirá o último trimestre (parte 4 de 4) em termos de número de bytes (não linhas), sem divisão de linhas:

split -n l/4/4 in.txt

Aqui está a documentação relevante para split -n CHUNKS :

CHUNKS may be: [...] l/K/N output Kth of N to stdout without splitting lines

No caso muito específico mencionado como exemplo na pergunta, 4/4 solicita o quarto trimestre ou os últimos 25% da entrada Arquivo. Para tamanhos que não são 1 / n da entrada, eu não acho que dividir fornece uma solução tão simples.

    
por 05.01.2018 / 20:23
5

Solução bash + stat + bc + tail para qualquer solução porcentagem:

get_last_chunk () { 
    local p=$(bc <<<"scale=2; $1/100")
    tail -c $(printf "%.0f" $(echo "$(stat -c%s $2) * $p" | bc)) "$2"
}
  • $1 e $2 - são os primeiro e segundo argumentos da função, respectivamente
  • p - variável atribuída com valor percentual como número flutuante (por ex. 0.14 ou 0.55 )
  • stat -c%s $2 - obtendo o tamanho real do arquivo de entrada em bytes
  • tail -c N $2 - obtendo os últimos N bytes do arquivo

Ou use a versão mais simplificada:

get_last_chunk () { 
    tail -c "$(($(stat -c%s - < "$2") * $1 / 100))" < "$2"))"
}

Assinatura : get_last_chunk <percent> <filename>

Amostra file.txt :

apples
oranges
bananas
cherries

Casos de teste:

get_last_chunk 17 file.txt
ries 
get_last_chunk 77 file.txt
oranges
bananas
cherries
get_last_chunk 29 file.txt
cherries
    
por 05.01.2018 / 20:48
0

Para obter o último $1 % em termos de número de linhas , portavelmente (POSIXly):

last_percent() (
  percent=${1?}; shift
  ret=0
  for file do
    lines=$(wc -l < "$file") &&
      tail -n "$((lines * percent / 100))" < "$file" || ret=$?
  done
  exit "$ret"
)

Exemplo:

$ seq 12 > a; printf '%s\n' aaaaaa bbbbb cccc dd > b
$ last_percent 25 a b
10
11
12
dd

Para o último $1 % em termos de número de bytes , substitua wc -l por wc -c e tail -n por tail -c . Cuidado, porém, que a primeira linha de saída provavelmente seria parcial. Nos mesmos arquivos acima, isso daria:

$ last_percent 25 a b
11
12
c
dd

Com o ksh93, você pode escrevê-lo apenas com builtins e não com um único fork como:

last_percent() (
  percent=$1; shift
  ret=0
  for file do
    command /opt/ast/bin/cat < "$file" <#((EOF*(100-percent)/100)) || ret=$?
  done
  exit "$ret"
)

Usando seu operador <#((...)) seeking.

O mesmo com zsh (exceto que cat não está lá):

zmodload zsh/system zsh/stat
last_percent() {
  local percent=$1 ret=0 file n
  shift
  for file do
    {
      sysseek -w end 0 &&
        sysseek -w end ' - systell(0) * percent / 100' &&
        cat
    } < $file || ret=$?
  done
  return $ret
}
    
por 06.01.2018 / 10:19