Anthony B
Anthony B

Reputation: 55

sorting numbers read in from input file in bash

So I have the following bash script, which is supposed to read a .txt file of an n amount of integers, add it to an array, sort the array using selection sort, then print the array:

a=()
filename="$1"
while IFS='' read -r line || [[ -n "$line" ]]; do
    a+=($line)
done < "$filename"

for((i=0; i<${#a[@]}; i++))
do
  min=$i
  for((j=$i+1; j<${#a[@]}; j++))
  do
    if (( ${a[$j]} <= ${a[$min]} ))
    then
      $min=$j
      echo "$min"
    fi
  done
  temp=a[$i]
  a[$i]=a[$min]
  a[$min]=$temp
done

for i in ${a[@]}
do
  echo $i
done

The problem is that the conditional within the inner loop throws an exception, where the problem I believe is that the array elements are all strings, and I'm not sure how to cast them to strings in this situation. Also, I don't think I'm swapping the two values properly. The output:

sh selectionsort.sh 10.txt
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 152ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 436ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 756ax error: invalid arithmetic operator (error token is "
 ") 391ax error: invalid arithmetic operator (error token is "
 ") 391ax error: invalid arithmetic operator (error token is "
 ") 391ax error: invalid arithmetic operator (error token is "
 ") 391ax error: invalid arithmetic operator (error token is "
 ") 391ax error: invalid arithmetic operator (error token is "
 ") 391ax error: invalid arithmetic operator (error token is "
 ") 435ax error: invalid arithmetic operator (error token is "
 ") 435ax error: invalid arithmetic operator (error token is "
 ") 435ax error: invalid arithmetic operator (error token is "
 ") 435ax error: invalid arithmetic operator (error token is "
 ") 435ax error: invalid arithmetic operator (error token is "
 ") 404ax error: invalid arithmetic operator (error token is "
 ") 404ax error: invalid arithmetic operator (error token is "
 ") 404ax error: invalid arithmetic operator (error token is "
 ") 404ax error: invalid arithmetic operator (error token is "
 ") 853ax error: invalid arithmetic operator (error token is "
 ") 853ax error: invalid arithmetic operator (error token is "
 ") 853ax error: invalid arithmetic operator (error token is "
 ") 278ax error: invalid arithmetic operator (error token is "
 ") 278ax error: invalid arithmetic operator (error token is "
 ") 643ax error: invalid arithmetic operator (error token is "
a[0]
a[1]
a[2]
a[3]
a[4]
a[5]
a[6]
a[7]
a[8]
a[9]

Any help is appreciated! Note: I know there's easier way to sort arrays, I'm using this script to implement selection sort.

Upvotes: 1

Views: 317

Answers (2)

Renaud Pacalet
Renaud Pacalet

Reputation: 29290

$min=$j is definitely an error. It should be min=$j. The way you access the cells of your array (temp=a[$i], a[$i]=a[$min]) too. Use temp=${a[$i]}, a[$i]=${a[$min]}, instead. But there are a few more things that you could improve:

declare -ai a=()
declare -i i j min temp
declare line

filename="$1"
while IFS='' read -r line; do
  [[ $line =~ ^[0-9]+$ ]] && a+=($line) || printf "Warning: not a number (%s)\n" "$line"
done < "$filename"

for (( i=0; i<${#a[@]}; i++ ))
do
  min=$i
  for (( j=i+1; j<${#a[@]}; j++ ))
  do
    if (( a[j] <= a[min] ))
    then
      min=$j
      echo "$min"
    fi
  done
  temp=${a[i]}
  a[i]=${a[min]}
  a[min]=$temp
done

for i in "${a[@]}"
do
  echo "$i"
done

In the context of arithmetic evaluation (((...))) and array indexing (a[...]), variable names are interpreted as their numeric values (no need of $).

I also added variable declarations and a test to eliminate non-integer entries.

Upvotes: 1

Mr. bug
Mr. bug

Reputation: 377

If you are using bash you can take advantage of its builtin functions like sort and readarray. (notice readarray is available since bash 4+, no OS X support by default.)

You can remove your sorting code and use the following code as described here

readarray -t sorted < <(for b in "${a[@]}"; do echo "$b"; done | sort)

$a will be transformed to a sorted array.

Upvotes: 1

Related Questions