Alinhar texto para centralizar com preenchimento em ambos os lados

5

Existe uma maneira fácil de alinhar o texto ao centro com preenchimento em ambos os lados, com a largura da coluna sendo a mais longa da entrada?

Por exemplo, isso:

aaa
bbbb
c
ddddd
ee

se transformará nisso (os pontos representam espaços):

.aaa.
bbbb.
..c..
ddddd
.ee..

Qualquer ferramenta está bem. Seja sed ou awk ou um monte de coreutils tools.

Editar : acho que alguns de vocês entendem mal a saída. A saída é preenchida com espaços , não em pontos. Eu usei pontos aqui só para deixar mais claro.

    
por Avidan Borisov 12.10.2013 / 14:28

4 respostas

2

Aqui está a minha solução, conforme postado em meu comente a resposta de Thor :

awk -v M="'wc -L file'" '{ printf "%*s%*s", (M+length)/2, $0, (M-length+1)/2+1, "\n" }' < file

Eu sinto que resolve o problema de forma elegante e sucinta e, portanto, estou repostando-o como uma resposta.

    
por 15.10.2013 / 13:31
3

Eu usaria o vim. Do modo normal:

:%center 5

... irá atuar em todas as linhas do arquivo (esse é o significado do % neste caso), centrando-o em cinco caracteres (referidos como colunas na documentação do vim). Isso vai agir exatamente como você descreve. Para obter a linha mais longa em um arquivo (para uso no comando center), use wc -L file.txt ; ou dentro do vim:

:! wc -L %

Infelizmente, isso não está disponível no vanilla vi, mas como isso é marcado como 'linux', é provável que você tenha o vim em seus repositórios, pelo menos.

Você também pode fazer isso em uma linha com:

vim file.txt -c '%center 5' -c 'wq' &> /dev/null

... mas tenho certeza de que não é o jeito mais rápido de fazer as coisas.

    
por 12.10.2013 / 16:24
3

Aqui está uma maneira de fazer isso com o awk ( pad.awk ):

# Determine length of longest line
FNR == NR { if(length > M) M = length; next }

# Pad each line according current line length (L) and longest line (M)
{
  L = M - length;
  for(i=1; i<=int(L/2); i++)
    printf "."
  printf "%s", $0
  for(i=1; i<=int(L/2+.5); i++)
    printf "."
  printf "\n"
}

Execute assim:

awk -f pad.awk infile infile

Saída:

.aaa.
bbbb.
..c..
ddddd
.ee..

Se você tem o GNU wc disponível, a linha mais longa pode ser encontrada com mais eficiência em wc -L . Isto é, solte a primeira linha de pad.awk e execute o awk assim:

awk -f pad.awk M=$(wc -L < infile) infile

Atualizar

Eu senti falta da parte sobre strings espaciais. De qualquer forma, é bastante simples permitir um caractere de preenchimento variável. Aqui está um exemplo completo com base nas ideias acima:

# Set padding character to the default (" ") if it was not set with -v
# Set ORS to "" to make printing easier
BEGIN { if(D == "") D = " "; ORS = "" }

# Pad each line according current line length (L) and longest line (M)
{
  L = M - length;
  for(i=1; i<=int(L/2); i++)
    print D
  print $0
  for(i=1; i<=int(L/2+.5); i++)
    print D
  print "\n"
}

Exemplo:

awk -v M=$(wc -L < infile) -v D=_ -f pad.awk infile

Saída:

_aaa_
bbbb_
__c__
ddddd
_ee__
    
por 12.10.2013 / 15:25
0

Com o Python:

#!/usr/bin/env python

with open('input.txt') as file:
    for line in file:
        l = line.strip()
        print l.center(5,'.'),"\n",

Nota: se você estiver usando a versão antiga do Python abaixo de 2.7, isso não funcionará.

Mesma saída:

rahul@home-pc:~/work$ python format_center.py
.aaa. 
.bbbb 
..c.. 
ddddd 
..ee.
    
por 12.10.2013 / 15:56