4

I'm quite new at bash and I am trying to learn it by creating some small scripts.

I created a small script to look up the DNS entry for multiple domains at the same time. The domains are given as attributes.

COUNTER=0 DOMAINS=() for domain in "$@" do WOUT_WWW=$(dig "$domain" +short) if (( $(grep -c . <<<"$WOUT_WWW") > 1 )); then WOUT_WWW="${WOUT_WWW##*$'\n'}" ; fi WITH_WWW=$(dig "www.${domain}" +short) if (( $(grep -c . <<<"$WITH_WWW") > 1 )); then WITH_WWW="${WITH_WWW##*$'\n'}" ; fi DOMAINS[$COUNTER]="$domain|$WOUT_WWW|$WITH_WWW" COUNTER=$(($COUNTER+1)) done 

Now I just want to loop through the new "multidimensional" array and give the output like mysql table:

+------------------------------+ | Row 1 | Row 2 | Row 3 | +------------------------------+ | Value | Value | Value | +------------------------------+ 

How can I do that?

4
  • The output of those dig commands may contain multiple lines (like dig www,google.com +short). Do you want to support that?CommentedSep 21, 2016 at 12:14
  • Eh, no. I forgot to mention, that I filter out only the last line (in probably all cases it's the IP address)CommentedSep 21, 2016 at 12:15
  • @StéphaneChazelas I added the "filtering" in the question-codeCommentedSep 21, 2016 at 12:19
  • 1
    See also: unix.stackexchange.com/q/310900/117549
    – Jeff Schaller
    CommentedSep 21, 2016 at 12:38

3 Answers 3

7

Using perl's Text::ASCIITable module (also supports multi-line cells):

print_table() { perl -MText::ASCIITable -e ' $t = Text::ASCIITable->new({drawRowLine => 1}); while (defined($c = shift @ARGV) and $c ne "--") { push @header, $c; $cols++ } $t->setCols(@header); $rows = @ARGV / $cols; for ($i = 0; $i < $rows; $i++) { for ($j = 0; $j < $cols; $j++) { $cell[$i][$j] = $ARGV[$j * $rows + $i] } } $t->addRow(\@cell); print $t' -- "$@" } print_table Domain 'Without WWW' 'With WWW' -- \ "$@" "${WOUT_WWW[@]}" "${WITH_WWW[@]}" 

Where the WOUT_WWW and WITH_WWW arrays have been constructed as:

for domain do WOUT_WWW+=("$(dig +short "$domain")") WITH_WWW+=("$(dig +short "www.$domain")") done 

Which gives:

.---------------------------------------------------------------------. | Domain | Without WWW | With WWW | +-------------------+----------------+--------------------------------+ | google.com | 216.58.208.142 | 74.125.206.147 | | | | 74.125.206.104 | | | | 74.125.206.106 | | | | 74.125.206.105 | | | | 74.125.206.103 | | | | 74.125.206.99 | +-------------------+----------------+--------------------------------+ | stackexchange.com | 151.101.65.69 | stackexchange.com. | | | 151.101.1.69 | 151.101.1.69 | | | 151.101.193.69 | 151.101.193.69 | | | 151.101.129.69 | 151.101.129.69 | | | | 151.101.65.69 | +-------------------+----------------+--------------------------------+ | linux.com | 151.101.193.5 | n.ssl.fastly.net. | | | 151.101.65.5 | prod.n.ssl.us-eu.fastlylb.net. | | | 151.101.1.5 | 151.101.61.5 | | | 151.101.129.5 | | '-------------------+----------------+--------------------------------' 
2
  • Wow. That's awesome! That's exactly what I was looking for. I already figured out a solution in bash, but this one is way better. Thank you!CommentedSep 21, 2016 at 12:52
  • function table-print() { perl -MText::ASCIITable -e ' $t = Text::ASCIITable->new({drawRowLine => 1}); while (defined($c = shift @ARGV) and $c ne "--") { push @header, $c; $cols++ } $t->setCols(@header); $rows = @ARGV / $cols; for ($i = 0; $i < $rows; $i++) { for ($j = 0; $j < $cols; $j++) { $cell[$i][$j] = $ARGV[$i * $cols + $j] } } $t->addRow(\@cell); print $t' -- "$@" } for table-print $headers[@] -- $row1[@] ...
    – HappyFace
    CommentedAug 6, 2020 at 12:10
0

I tried a lot of variations and done some researches. Following code is working great for me:

for DOMAIN in "${DOMAINS[@]}"; do printf "%-8s\n" "${DOMAIN}" done | sed -e 's/|/_|g' | column -t -s '_' | awk '1;! (NR%1){print "---------";}' 

Just looping through my array. I'm using sed because I have a delimiter in my array-values to split them up. But column was that what I was searching for.

1
  • 1
    ! (NR%1) is a strange obfuscating way of saying true...
    – JJoao
    CommentedSep 21, 2016 at 15:01
0
function printTable() { local -r delimiter="${1}" local -r data="$(removeEmptyLines "${2}")" if [[ "${delimiter}" != '' && "$(isEmptyString "${data}")" = 'false' ]] then local -r numberOfLines="$(wc -l <<< "${data}")" if [[ "${numberOfLines}" -gt '0' ]] then local table='' local i=1 for ((i = 1; i <= "${numberOfLines}"; i = i + 1)) do local line='' line="$(sed "${i}q;d" <<< "${data}")" local numberOfColumns='0' numberOfColumns="$(awk -F "${delimiter}" '{print NF}' <<< "${line}")" # Add Line Delimiter if [[ "${i}" -eq '1' ]] then table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")" fi # Add Header Or Body table="${table}\n" local j=1 for ((j = 1; j <= "${numberOfColumns}"; j = j + 1)) do table="${table}$(printf '#| %s' "$(cut -d "${delimiter}" -f "${j}" <<< "${line}")")" done table="${table}#|\n" # Add Line Delimiter if [[ "${i}" -eq '1' ]] || [[ "${numberOfLines}" -gt '1' && "${i}" -eq "${numberOfLines}" ]] then table="${table}$(printf '%s#+' "$(repeatString '#+' "${numberOfColumns}")")" fi done if [[ "$(isEmptyString "${table}")" = 'false' ]] then echo -e "${table}" | column -s '#' -t | awk '/^\+/{gsub(" ", "-", $0)}1' fi fi fi } function removeEmptyLines() { local -r content="${1}" echo -e "${content}" | sed '/^\s*$/d' } function repeatString() { local -r string="${1}" local -r numberToRepeat="${2}" if [[ "${string}" != '' && "${numberToRepeat}" =~ ^[1-9][0-9]*$ ]] then local -r result="$(printf "%${numberToRepeat}s")" echo -e "${result// /${string}}" fi } function isEmptyString() { local -r string="${1}" if [[ "$(trimString "${string}")" = '' ]] then echo 'true' && return 0 fi echo 'false' && return 1 } function trimString() { local -r string="${1}" sed 's,^[[:blank:]]*,,' <<< "${string}" | sed 's,[[:blank:]]*$,,' } 

SAMPLE RUNS

$ cat data-1.txt HEADER 1,HEADER 2,HEADER 3 $ printTable ',' "$(cat data-1.txt)" +-----------+-----------+-----------+ | HEADER 1 | HEADER 2 | HEADER 3 | +-----------+-----------+-----------+ $ cat data-2.txt HEADER 1,HEADER 2,HEADER 3 data 1,data 2,data 3 $ printTable ',' "$(cat data-2.txt)" +-----------+-----------+-----------+ | HEADER 1 | HEADER 2 | HEADER 3 | +-----------+-----------+-----------+ | data 1 | data 2 | data 3 | +-----------+-----------+-----------+ $ cat data-3.txt HEADER 1,HEADER 2,HEADER 3 data 1,data 2,data 3 data 4,data 5,data 6 $ printTable ',' "$(cat data-3.txt)" +-----------+-----------+-----------+ | HEADER 1 | HEADER 2 | HEADER 3 | +-----------+-----------+-----------+ | data 1 | data 2 | data 3 | | data 4 | data 5 | data 6 | +-----------+-----------+-----------+ $ cat data-4.txt HEADER data $ printTable ',' "$(cat data-4.txt)" +---------+ | HEADER | +---------+ | data | +---------+ $ cat data-5.txt HEADER data 1 data 2 $ printTable ',' "$(cat data-5.txt)" +---------+ | HEADER | +---------+ | data 1 | | data 2 | +---------+ 

REF LIB at: https://github.com/gdbtek/linux-cookbooks/blob/master/libraries/util.bash

1
  • HEADS UP! The ref link have a more updated function.
    – insign
    CommentedMar 18, 2020 at 16:05

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.