Encurte linhas, adicionando reticências “…”

5

Como cortar linhas com mais de uma largura, e marcando as linhas que foram cortadas com reticências?

Somente as linhas que foram realmente reduzidas devem ser marcado, mas não linhas que tiveram o comprimento certo em primeiro lugar.

Eu gostaria de usar o comando em um pipeline.

    
por Volker Siegel 14.09.2014 / 13:04

6 respostas

12

Isso truncará a string, cortará três caracteres adicionais e adicionará "..." se o tamanho for maior que o valor fornecido como parâmetro.

other_programs | \
awk -v len=40 '{ if (length($0) > len) print substr($0, 1, len-3) "..."; else print; }'
    
por Mark Plotnick 14.09.2014 / 15:14
6

Tente isto:

awk -F '' '{if (NF > 70) {print substr($0, 0, 71)"..."} else print $0}'

Se a NF for muito alta, a maneira mais simples:

awk '{if (length($0) > 70) {print substr($0, 0, 71)"..."} else print $0}'

ou uma versão mais curta:

awk 'length > 70{$0=substr($0,0,71)"..."}1'
    
por muru 14.09.2014 / 13:17
4

Algumas possibilidades:

  • com sed

    sed -E 's/(.{N})(.{1,})$/.../' file
    
  • um pouco mais elegantemente com perl (usando lookbehind)

    perl -pe 's/(?<=.{N}).{1,}$/.../' file
    

onde N é o número de caracteres após os quais você deseja substituir as reticências.

    
por steeldriver 14.09.2014 / 13:19
3

awk , sed e perl , conforme apresentado nas outras respostas, é excelente no processamento de texto e provavelmente é a melhor ferramenta para o trabalho.

Mas você também pode fazer isso em bash puro (ou seja, , "sem deixar o shell"), se você quiser:

n=70
while read -r; do
    if ((${#REPLY}<=n))
        then printf '%s\n' "$REPLY"
        else printf '%s...\n' "${REPLY:0:$((n-3))}"
    fi
done < filename

Substitua 70 pelo comprimento máximo desejado e filename pelo arquivo de entrada.

Para usar isso no lado direito de um pipe (ou seja, para canalizar a saída de outro comando para ele), remova < filename e defina n antes ou coloque tudo em { ... ;} :

{ n=70
while read -r; do
    if ((${#REPLY}<=n))
        then printf '%s\n' "$REPLY"
        else printf '%s...\n' "${REPLY:0:$((n-3))}"
    fi
done ;}

(Esta versão entre colchetes também funciona bem em outros contextos, incluindo o redirecionamento como acima. Os colchetes são desnecessários nesse caso de uso, mas não são prejudiciais.)

Isso parece:

ek@Ilex:~$ help read | head -5 | { n=70
> while read -r; do
>     if ((${#REPLY}<=n))
>         then printf '%s\n' "$REPLY"
>         else printf '%s...\n' "${REPLY:0:$((n-3))}"
>     fi
> done ;}
read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N n...
    Read a line from the standard input and split it into fields.

    Reads a single line from the standard input, or from file descr...
    if the -u option is supplied.  The line is split into fields as...

Observe que, em comum com as outras soluções apresentadas até agora, isso não conseguirá limitar perfeitamente a largura da saída na presença de caracteres que exibem mais de uma coluna de largura, como guias horizontais .

    
por Eliah Kagan 18.09.2014 / 00:12
0

A resposta aceita escrita como uma função com o exemplo, também colocando o ... no meio da string ao invés do final:

truncate() {    
    echo "$@" | \
    awk -v len=15 '{ if (length($0) > len) print substr($0, 1, len-3) "..." substr($0, length($0) - len, length($0)); else print; }'
}

exemplo:

parse_branch() {
    branch=$(git symbolic-ref --short HEAD || hg branch)
    truncate "$branch"
}
    
por 21.06.2018 / 09:11
0

Outra solução perl :

perl -ple '$_ = sprintf "%.70s...", $_ if length > 70' file
    
por cuonglm 14.09.2014 / 13:35