Shell Bash Script to Print Numbers in Ascending Order

Shell Bash script to print numbers in ascending order

You can use this script:

#!/bin/bash
IFS=' ' read -ra arr -p "Enter numbers: "
Enter numbers: 4 -1 2 66 10

sort -n <(printf "%s\n" "${arr[@]}")
-1
2
4
10
66
  • IFS=' ' to make read all number delimited by space
  • 'read -ra` to read all numbers in an array
  • sort -n to sort numbers numerically
  • printf "%s\n" "${arr[@]}" to print each element of array in separate line
  • <(printf "%s\n" "${arr[@]}") is process substitution that make it printf command behave like a file for sort -n command.

sorting an output in numeric order bash

Using GNU awk:

awk 'NR==1 { print;next } { split($4,map,":");map1[map[1]][map[2]][map[3]]=$0} END { PROCINFO["sorted_in"]="@ind_num_asc";for ( i in map1 ) { for ( j in map1[i]) { for ( k in map1[i][j]) { print map1[i][j][k] } } } }' file

Explanation:

awk 'NR==1 { 
print; # For the first line ( headers) print and skip to the next line
next
}
{ split($4,map,":"); # Split the fourth space separated field into the array map using ":" as the delimiter
map1[map[1]][map[2]][map[3]]=$0 # Create a 3 dimensional array called map with the first, second and third indexes of map as the indexes and the line as the value
}
END {
PROCINFO["sorted_in"]="@ind_num_asc"; # Set the array ordering (index number ascending)
for ( i in map1 ) {
for ( j in map1[i]) {
for ( k in map1[i][j]) {
print map1[i][j][k] # At the end of processing the file, loop through the map1 array and print the values.
}
}
}
}' file

Sorting numbers in a row on the BASH / Shell

try this;

#!/bin/bash
while read line
do
beforeC=$(echo "$line" | cut -f-5 -d';')
sortcolumn=$(echo "$line" | awk -F ";" '{print $6}' | tr -t , "\n" | sort -r -n | xargs | sed 's/ /,/g')
afterC=$(echo "$line" | cut -f7- -d';')
echo -e $beforeC";"$sortcolumn";"$afterC
done <file

user@host:/tmp/test$ cat file
00000000000000;000022233333;2;NONE;true;100,100,5,1,28;UNKNOWN
00000000000000;000022233333;2;NONE;true;99,100,5,1,28;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,99,5,1,28;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,100,4,1,28;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,100,4,0,28;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,100,4,1,27;UNKNOWN

user@host:/tmp/test$ ./sortAColumn.sh
00000000000000;000022233333;2;NONE;true;100,100,28,5,1;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,99,28,5,1;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,99,28,5,1;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,100,28,4,1;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,100,28,4,0;UNKNOWN
00000000000000;000022233333;2;NONE;true;100,100,27,4,1;UNKNOWN

sort alphanumerically with priority for numbers in linux

So, basically, you're asking to sort the first field numerically in descending order, but if the numeric keys are the same, you want the second field to be ordered in natural, or ascending, order.

I tried a few things, but here's the way I managed to make it work:

   sort -nk2 file.txt  | sort -snrk1

Explanation:

  • The first command sorts the whole file using the second, alphanumeric field in natural order, while the second command sorts the output using the first numeric field, shows it in reverse order, and requests that it be a "stable" sort.

  • -n is for numeric sort, versus alphanumeric, in which 6 would come before 60.

  • -r is for reversed order, so from highest to lowest. If unspecified, it will assume natural, or ascending, order.
  • -k which key, or field, to use for sorting order.
  • -s for stable ordering. This option maintains the original record order of records that have an equal key.

Bash:: How to sort according to first numeric column of file?

How about this:

sed -e 's/^[^0-9.]*\([0-9.]\+\).*$/\1\t\0/' input | sort -n | cut -f 2-

We extract the first numeric field and we insert it to the beginning of each line. Then we sort numerically all lines and then we remove the stuff that we added in the first step.

shell script to print and sort the date column in csv

It should be sort -t, -nk4 (- is missing before options).

To output only the 10 first lines, you can pipe your sort to head:

sort -t, -nk4 file.csv | head -n10 > /tmp/s.csv

The same maybe a bit more readable:

sort -t ","  -k 4 -n file.csv | head -n10 > /tmp/s.csv

head -n10 is to print only the 10 first line of the sort output.

How to sort an array in Bash

You don't really need all that much code:

IFS=$'\n' sorted=($(sort <<<"${array[*]}"))
unset IFS

Supports whitespace in elements (as long as it's not a newline), and works in Bash 3.x.

e.g.:

$ array=("a c" b f "3 5")
$ IFS=$'\n' sorted=($(sort <<<"${array[*]}")); unset IFS
$ printf "[%s]\n" "${sorted[@]}"
[3 5]
[a c]
[b]
[f]

Note: @sorontar has pointed out that care is required if elements contain wildcards such as * or ?:

The sorted=($(...)) part is using the "split and glob" operator. You should turn glob off: set -f or set -o noglob or shopt -op noglob or an element of the array like * will be expanded to a list of files.

What's happening:

The result is a culmination six things that happen in this order:

  1. IFS=$'\n'
  2. "${array[*]}"
  3. <<<
  4. sort
  5. sorted=($(...))
  6. unset IFS

First, the IFS=$'\n'

This is an important part of our operation that affects the outcome of 2 and 5 in the following way:

Given:

  • "${array[*]}" expands to every element delimited by the first character of IFS
  • sorted=() creates elements by splitting on every character of IFS

IFS=$'\n' sets things up so that elements are expanded using a new line as the delimiter, and then later created in a way that each line becomes an element. (i.e. Splitting on a new line.)

Delimiting by a new line is important because that's how sort operates (sorting per line). Splitting by only a new line is not-as-important, but is needed preserve elements that contain spaces or tabs.

The default value of IFS is a space, a tab, followed by a new line, and would be unfit for our operation.

Next, the sort <<<"${array[*]}" part

<<<, called here strings, takes the expansion of "${array[*]}", as explained above, and feeds it into the standard input of sort.

With our example, sort is fed this following string:

a c
b
f
3 5

Since sort sorts, it produces:

3 5
a c
b
f

Next, the sorted=($(...)) part

The $(...) part, called command substitution, causes its content (sort <<<"${array[*]}) to run as a normal command, while taking the resulting standard output as the literal that goes where ever $(...) was.

In our example, this produces something similar to simply writing:

sorted=(3 5
a c
b
f
)

sorted then becomes an array that's created by splitting this literal on every new line.

Finally, the unset IFS

This resets the value of IFS to the default value, and is just good practice.

It's to ensure we don't cause trouble with anything that relies on IFS later in our script. (Otherwise we'd need to remember that we've switched things around--something that might be impractical for complex scripts.)

How can I add a column of ascending numbers for each scaffold in my bed file

All right, I finished a bash script that will do exactly what you need. Go ahead and save the following as num_count.sh (or whatever you want as long as it's a shell script format) and it should do the trick for you:

#!/bin/bash

#Color declarations
RED='\033[0;31m'
GREEN='\033[0;32m'
LIGHTBLUE='\033[1;34m'
LIGHTGREEN='\033[1;32m'
NC='\033[0m' # No Color

#Ignore the weird spacing. I promise it looks good when it's echoed out to the screen.
echo -e ${LIGHTBLUE}"############################################################"
echo "# Running string counting script. #"
echo "# #"
echo -e "# ${LIGHTGREEN}Syntax: num_count.sh inputFile outputFile${LIGHTBLUE} #"
echo "# #"
echo "# The script will count the number of instances of #"
echo "# the first string and increment the number as it #"
echo "# finds a new one, appending it to the end of each line. #"
echo -e "############################################################"${NC}

numCount=0
oldStr=null
if [ -z "$1" ] || [ -z "$2" ]; then
echo "Insufficient arguments. Please correct your parameters and run the script again."
exit
fi
> $2
while IFS= read -r line; do
firstStr=$(echo $line | awk '{print $1;}')
if [ $oldStr == $firstStr ] ; then
((numCount++))
echo -e "$line\t$numCount" >> $2
else
oldStr=$firstStr
numCount=0
echo -e "$line\t$numCount" >> $2
fi
done < $1

Essentially, you'll need to run the script with the first argument as the file that contains the lines you want counted, and the second argument as the output file. Be careful because the output file will be overwritten with the output data. I hope this helps!

Here's the before and after:

Before:


SCF_1 0 1
SCF_1 3 4
SCF_1 9 10
SCF_2 0 1
SCF_2 4 5
SCF_2 12 13
SCF_2 23 24
SCF_2 79 80
SCF_3 2 3
SCF_4 1 2

After:


SCF_1 0 1 0
SCF_1 3 4 1
SCF_1 9 10 2
SCF_2 0 1 0
SCF_2 4 5 1
SCF_2 12 13 2
SCF_2 23 24 3
SCF_2 79 80 4
SCF_3 2 3 0
SCF_4 1 2 0


Related Topics



Leave a reply



Submit