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? Commented Mar 17 at 14:11
  • please update the question with the code you've tried and the (wrong) results generated by said code Commented Mar 17 at 14:48

4 Answers 4

1

Using sed:

sed 's/true/│ /g; s/false/  /g' <<< "${arr[*]}"
Sign up to request clarification or add additional context in comments.

Comments

1

With a for loop:

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

Comments

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 Comment

Your test-drive doesn't produce complete lines - final printf of each block needs to add \n or change to echo.
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...

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.