beacher_pille88
beacher_pille88

Reputation: 69

Sorting a list with multi-part items

third try to understand what Im doing wrong.

Ive got a list like this:

array[0] = 1111 Here is much text
array[1] = 2222 Here is even more text
array[2] = 1111.1 Here is special text

Now I want to sort the list to have it like this:

1111 Here is much text
1111.1 Here is special text
2222 Here is even more text

Using

for j in ${array[@]}; do echo $j; done | sort -n

it seperates me every single part because of the spaces.

Using

for j in "${array[@]}"; do echo "$j"; done | sort -n

I get a sorted list like 1111 2222 1111.1

Upvotes: 0

Views: 120

Answers (2)

glenn jackman
glenn jackman

Reputation: 247012

array=(
    "1111 Here is much text" 
    "2222 Here is even more text" 
    "1111.1 Here is special text"
)
printf "%s\n" "${array[@]}" | sort -n
1111 Here is much text
1111.1 Here is special text
2222 Here is even more text

To save it:

sorted=()
while IFS= read -r line; do
    sorted+=("$line")
done  < <( printf "%s\n" "${array[@]}" | sort -n )
printf "%s\n" "${sorted[@]}"
# same output as above

or

source <( echo 'sorted=('; printf '"%s"\n' "${array[@]}" | sort -n; echo ')' )
printf "%s\n" "${sorted[@]}"

Carriage returns in your file will mess you up. Consider file named "t" with dos-style line endings:

$ cat -e t
line1^M$
line2^M$
line3^M$
$ for n in {1..3} ; do array[n]="$(echo $n $(cat t))"; done
$ printf "%s\n" "${array[@]}"|od -c
0000000   1       l   i   n   e   1  \r       l   i   n   e   2  \r    
0000020   l   i   n   e   3  \r  \n   2       l   i   n   e   1  \r    
0000040   l   i   n   e   2  \r       l   i   n   e   3  \r  \n   3    
0000060   l   i   n   e   1  \r       l   i   n   e   2  \r       l   i
0000100   n   e   3  \r  \n
0000105
$ printf "%s\n" "${array[@]}"
 line31
 line31
 line31

Clearly this is going to mess up anything you feed with this input. Fix the carriage returns.

Upvotes: 3

Uwe
Uwe

Reputation: 728

Your locale is set in such a way that the . is interpreted as a thousands separator, rather than a decimal point, and the numeric values are sorted accordingly (1111.1 is interpreteted as 11111, e.g. with LC_ALL=de_DE). Use

export LC_ALL=C

before you execute sort (and, of course, use proper quoting, as in glenn's and fedorqui's answers).

Upvotes: 0

Related Questions