5

Is there an easy way to align text to the center with padding on both sides, with the column width being the longest line from the input?

For example, this:

aaa
bbbb
c
ddddd
ee

will turn into this (the dots represent spaces):

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

Any tool is fine. Be it sed or awk or a bunch of coreutils tools.

Edit: I think some of you misunderstood the output. The output is padded with spaces, not dots. I've used dots here just to make it more clear.

3

I'd use vim. From normal mode:

:%center 5

...will act on every line in the file (that's the meaning of the % in this case), centring it to five characters (referred to as columns in the vim documentation). This will act exactly as you describe. To get the longest line in a file (for use in the center command), use wc -L file.txt; or within vim:

:! wc -L %

Unfortunately this isn't available in vanilla vi, but since this is tagged 'linux' it's likely that you have vim in your repositories at least.

You can also do this in one line with:

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

...but I'm sure that's not the fastest way of doing things.

3

Here is one way you could do it with 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"
}

Run it like this:

awk -f pad.awk infile infile

Output:

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

If you have GNU wc available, the longest line can more efficiently be found with wc -L. That is, drop the first line of pad.awk and run awk like this:

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

Update

I missed the bit about space-padded strings. Anyway, it is fairly straightforward to allow for a variable padding character. Here is a complete example based on the ideas from above:

# 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"
}

Example:

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

Output:

_aaa_
bbbb_
__c__
ddddd
_ee__
3
  • 1
    Thanks, did not know about wc -L. Ended up with this: awk -v M="`wc -L file`" '{ printf "%*s%*s", (M+length)/2, $1, (M-length+1)/2+1, "\n" }' < file after spending some time learning awk basics. – Avidan Borisov Oct 12 '13 at 16:01
  • @Avidanborisov: nice solution, feel free to post it as an answer, or, if you prefer, add it to this answer – Thor Oct 15 '13 at 10:36
  • OK, just did :-) – Avidan Borisov Oct 15 '13 at 11:42
2

Here's my solution, as posted in my comment to Thor's answer:

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

I feel it solves the problem elegantly and succinctly, and therefore I'm reposting it as an answer.

0

With Python :

#!/usr/bin/env python

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

Note: if you are using Python Old version below 2.7 then this will not work.

Same output :

rahul@home-pc:~/work$ python format_center.py
.aaa. 
.bbbb 
..c.. 
ddddd 
..ee.
1
  • The question says “the column width being the longest line from the input”. Better detect the width in your script. – manatwork Oct 12 '13 at 14:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.