views:

222

answers:

4

I wanted to display a long list of strings from an array.

Right now, my script run through a for loop echoing each value to the standard output:

for value in ${values[@]}
do
  echo $value
done

Yeah, that's pretty ugly! And the one column listing is pretty long too...

I was wondering if i can find a command or builtin helping me to display all those values in columns, like the ls command does by default when listing a directory (ls -C).

[Update]

Losing my brain with column not displaying properly formatted columns, here's more info:

The values: $ values=( 01----7 02----7 03-----8 04----7 05-----8 06-----8 07-----8 08-----8 09---6 10----7 11----7 12----7 13----7 14-----8 15-----8 16----7 17----7 18---6 19-----8 20-----8 21-----8) (Notice the first two digits as an index and the last one indicating the string length for readability)

The command: echo " ${values[@]/%/$'\n'}" | column

The result: bad columns

Something is going wrong...

A: 

Tabspaces


Use a tab after each value.

( It automatically flows to next line too... )

for value in ${values[@]}
do
  echo -en "$value\t"
done

Detailed info here

GoodLUCK!!
- CVS

CVS-2600Hertz
I'm pretty sure you mean `echo -en "$value\t"`
Dennis Williamson
@Dennis Updated!
CVS-2600Hertz
+4  A: 

You could pipe your output to column.

column seems to struggle with some data in a single-column input being narrower than a tabstop (8 characters). Using a for-loop, padding to 8 characterss seems to do the trick:

for item in "${values[@]}"; do 
    printf "%-8s\n" "${item}"
done | column
Johnsyweb
+1 Correct! `column` for column-wise output and `column -x` for row-wise output.
Dennis Williamson
@Johnsyweb and @Dennis: Nice one! That's exactly what i was looking for. But the result is not perfect: depending on the strings lenght, there's sometimes holes in the columns. It feels like it snaps the columns size at some width (like tabs inserted between values) but does not take care of the largest value lenght to compute the column overall width. The `ls` command does take care of this for a clean output.
Arko
+1  A: 

Here are a couple of techniques that can be used with Johnsyweb's answer so you can do your output without a loop:

saveIFS=$IFS
IFS=$'\n'
echo "${values[*]}" | column
IFS=$saveIFS

or

echo " ${arr[@]/%/$'\n'}" | column

or

echo " ${arr[@]/%/$'\n'}" | sed 's/^ //' | column
Dennis Williamson
@Dennis: Nice! Tried all three techniques, roughly same result. See my comment on @Johnysweb's answer.
Arko
@Arko: Without seeing your data it's impossible to make any further suggestions. `columns` does use tabs and it also adjusts the number of columns based on the length of the longest string.
Dennis Williamson
@Dennis: My data is a simple array of strings, like `values=(one two three four five)'. I must have missed something. No way to get a properly formatted column. Will update question with more info about it.
Arko
@Arko: Your data lines up perfectly for me using the command you supplied. I was not able to reproduce exactly what your screenshot shows, but I came close by narrowing my terminal window to 60 characters wide and issuing a `tabs -10` command before issuing your `echo ... column` command.
Dennis Williamson
@Dennis: I was expecting your answer. The problem is specific to my computer. I'll try to track down why. In the mean time, i found an other "way" to do it... See my own answer. ;)
Arko
+1  A: 

It may look overkill, but i came up with my own solution. I wrote a little script that does exactly what i wanted: take a list of values and output them in a pretty formatted column view.

http://github.com/Arko/Columnize

Arko
Suggestions: integer comparison: `if (( ${#value} > $longest_value ))` and others, you use `(())` elsewhere - you can here, too: `((columns = term_width / (longest_value + 2) ))` and `((spaces_missing = longest_value - value_len + 2 ))`, instead of echoing spaces in a `for` loop: `printf "%*s" $spaces_missing`
Dennis Williamson
@Dennis Williamson: Changes committed! I knew that `for` loop was awkward... Thank you for the suggestions! :-)
Arko