Losing formatting using “echo -e” in bash

2019-08-01 03:46发布

问题:

I'm having a problem with the following snippet:

while read line
do
     team1=`echo "${line% *}"`
     team2=`echo "${line#* }"`
     newline=`printf "%-8.2f\t%-8.2f\n" "$team1" "$team2"`
     #this line give perfect output
     # echo "$newline" 
     ##################problem is here########################
     final_list=("${final_list[@]}" "$newline")
     #########################################################
done <input.txt

#this line is losing all the formatting I gave
echo -e ${final_list[@]} | sort -t$'\t' -k1 -nr

This is my input file

3.01 16.12
1.12 13.22
3.01 14.12 

My expected output is

1.12            13.22   
3.01            14.12   
3.01            16.12 

回答1:

Replace:

echo -e ${final_list[@]} | sort -t$'\t' -k1 -nr

with:

printf "%s\n" "${final_list[@]}" | sort -t$'\t' -k1 -n

This achieves your expected output:

$ printf "%s\n" "${final_list[@]}" | sort -t$'\t' -k1 -n
1.12            13.22   
3.01            14.12   
3.01            16.12   

There were two required changes. First, sort works line-by-line and the echo output produces a single line. Second, because your desired output was numerically sorted in ascending order, the -r flag needed to be removed from sort.

What went wrong

This line does not do what one would think:

 newline=`printf "%-8.2f\t%-8.2f\n" "$team1" "$team2"`

The problem is that, when the shell does command substitution, any trailing newline characters are deleted. So, the \n in the printf format is removed before the output is assigned to newline.

That means that when you get to here:

echo -e ${final_list[@]} 

There are no newlines. The echo output all appears on one line.

Now, consider:

 #this line give perfect output
 # echo "$newline" 

That works because echo adds its own newline to the output.

A simpler script

I don't know the structure of your big project, but, as a possible alternative to the code presented, consider:

while read team1 team2
do
     newline=$(printf "%-8.2f\t%-8.2f" "$team1" "$team2")
     final_list=("${final_list[@]}" "$newline")
done <input.txt
printf "%s\n" "${final_list[@]}" | sort -t$'\t' -k1 -n

Still simpler, but possibly not helpful in the big project, would be this code which reformats and sorts input.txt:

$ awk '{printf "%-8.2f\t%-8.2f\n",$1,$2}' input.txt |sort -n
1.12            13.22   
3.01            14.12   
3.01            16.12   


回答2:

Use sort -n to sort the file (if needed redirect it to new file like > newfile.txt and use it)?

sort -n input.txt


标签: bash shell