Using tput changes the length of the string and so columns are not aligned. How to fix this?
Tried following code in bash script.
B="$(tput bold)" # Bold text
N="$(tput sgr0)" # Normal text
function testing(){
IN="KEYS | VALUES | DESCRIPTION
id | ${B}10${N} or ${B}20${N} | Enter ID. Default is ${B}10${N}.
status | ${B}true${N} or ${B}false${N} | Enter status of something. Default is ${B}true${N}.
style | Example: Standard | Give suitable standard."
IFS=
while read -r lines; do
IFS='|' read -r -a array <<< "$lines"
printf "%-35s %-35s %-s\n" "${array[0]}" "${array[1]}" "${array[2]}"
done <<< "$IN"
read -p "$*"
exit 0
}
Output is something like:
KEYS VALUES DESCRIPTION
id **10** or **20** Enter ID. Default is **10**.
status **true** or **false** Enter status of something. Default is **true**.
style Example: Standard Give suitable standard.
Expected to be:
KEYS VALUES DESCRIPTION
id **10** or **20** Enter ID. Default is **10**.
status **true** or **false** Enter status of something. Default is **true**.
style Example: Standard Give suitable standard.
As I mentioned in my comment:
DESCRIPTION
strings lose 20 spaces of indent${#B}
& ${#N}
) are 4 and 6 chars, respectivelyVALUES
field for a total of 20 (non-printable) charsprintf/%s
counts the 20 non-printable chars as part of the output hence the appearance that 20 spaces are 'lost' (ie, printf
is printing 35 chars ... it's just that 20 of those chars are non-printing)What if we measure the length of the second field - with and without the special chars
- and then use the difference (ie, the number of non-printable characters) to increase the format width of the second field of the printf
command?
We'll store the length of the second field (which includes our special characters) in a new variable len2
:
len2="${#array[1]}"
Next we want to strip out the special characters and measure the length of the resulting string and place in variable lenx
:
x="${array[1]//${B}/}" # strip out all occurrences of variable 'B'
x="${x//${N}/}" # strip out all occurrences of variable 'N'
lenx=${#x}
NOTE: I had some problems getting tr
and sed
to properly strip out the special characters; I'm open to suggestions. On the plus side ... I'm not spawning any sub processes.
We'll store the new format width in variable w2
('w'idth for field '2') like such:
w2=$(( 35 + len2 - lenx ))
And the new printf
format string becomes:
printf "%-35s %-${w2}s %-s\n" ...
Pulling it all together we get:
B="$(tput bold)" # Bold text
N="$(tput sgr0)" # Normal text
function testing(){
IN="KEYS | VALUES | DESCRIPTION
id | ${B}10${N} or ${B}20${N} | Enter ID. Default is ${B}10${N}.
status | ${B}true${N} or ${B}false${N} | Enter status of something. Default is ${B}true${N}.
style | Example: Standard | Give suitable standard."
IFS=
while read -r lines; do
IFS='|' read -r -a array <<< "$lines"
len2="${#array[1]}"
x="${array[1]//${B}/}"
x="${x//${N}/}"
lenx=${#x}
w2=$(( 35 + len2 - lenx ))
# echo "w2 = ${w2}"
printf "%-35s %-${w2}s %-s\n" "${array[0]}" "${array[1]}" "${array[2]}"
done <<< "$IN"
read -p "$*"
exit 0
}
Running the script in my bash env generates:
$ testing
KEYS VALUES DESCRIPTION
id 10 or 20 Enter ID. Default is 10.
status true or false Enter status of something. Default is true.
style Example: Standard Give suitable standard.
NOTE: The bold fields do print as bold on my terminal ... they just don't copy/display as bold in the above answer.
If you uncomment the line - echo "w2 = ${w2}"
- you should find (for the 2 lines of interest) that we're going to use a format width of 55
for the second field (ie, the desired 35
plus an extra 20
to compensate for the 20 characters worth of non-printable characters).