0

I am trying to create a tree structure like the tree command.

To keep track of the "heirarchy", I have an array like ("true" "true" "false") or ("true" "false" "false") or ("false" "true" "true") etc.

I want to build a string (that I will use to print the result on the terminal) which has Unicode based on the array.

For example ("true" "true" "false") would result in "│ │ "

("true" "false" "false") would result in in "│ "

and

("false" "true" "true") would result in " │ │ "

Where false is 2 spaces, true is unicode character \u2502 and a space. With the printf "%6s" | sed $'s/ /\u2502 /' command I can create spaces and replace one or all spaces (or 2 spaces) with unicode chars manually but I want to do it programmatically and also, the length on the array will change, doing manually can get very cumbersome.

Can someone guide? I am basically trying to add the lines in the places shown by red squiggles in the pic below

enter image description here

2
  • Use a for loop?
    – Shawn
    Commented Mar 17 at 14:11
  • please update the question with the code you've tried and the (wrong) results generated by said code
    – markp-fuso
    Commented Mar 17 at 14:48

4 Answers 4

1

Using sed:

sed 's/true/│ /g; s/false/  /g' <<< "${arr[*]}"
1

With a for loop:

for e in "${foo[@]}"; do 
    printf "%s" "$([[ $e == "true" ]] && echo '|' || echo ' ')"
done
0
1

Define an associative array with the desired mappings, eg:

declare -A map=([true]=$'\u2502 ' [false]='  ')

A simple for loop can then be used to step through the main array, printing the associated mapping characters on each pass through the loop, eg:

for i in "${arr[@]}"
do
    printf "%s" "${map[$i]}"
done

NOTES: OP can follow this up with additional printf calls to finish populating a line of output; a simple printf "\n" or echo "" would suffice to terminate the line

Taking for a test drive (: added as prefix/suffix to show spacing):

$ arr=("true" "true" "false")
$ printf ":"; for i in "${arr[@]}"; do printf "%s" "${map[$i]}"; done; printf ":"
:│ │   :

$ arr=("true" "false" "false")
$ printf ":"; for i in "${arr[@]}"; do printf "%s" "${map[$i]}"; done; printf ":"
:│     :

$ arr=("false" "true" "true")
$ printf ":"; for i in "${arr[@]}"; do printf "%s" "${map[$i]}"; done; printf ":"
:  │ │ :
1
  • 1
    Your test-drive doesn't produce complete lines - final printf of each block needs to add \n or change to echo. Commented Mar 17 at 16:09
1

Since we control the array, and only ever enter true or false, we can use those values as conditions:

arr=(true true false true)
for i in "${arr[@]}"
do if $i
   then printf '│ '
   else printf '  '
   fi
done
printf '- %s\n' ...name...

However, it might be better to store either or as each value in the array instead of true or false, allowing us to print the values directly without writing a loop:

arr=('│ ' '│ ' '  ' '│ ')
printf %s "${arr[@]}"
printf '├%s\n' ...name...

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.