1

I have a list of numbers and null values. How can I sort them in a way such that the null values come to the end of the list using sort in GNU coreutils?

A sample column of input (input.data)

0.9000
23

1
2
5

-0.9000
-23

-1
-2
-5

When I tried to with sort -g input.data, the output is as follows.

<NULL>
<NULL>
<NULL>
-23
-5
-2
-1
-0.9000
0.9000
1
2
5
23

Here null values are placed at the top. Is it possible to get the null values to the end of the list? Expected as following:

-23
-5
-2
-1
-0.9000
0.9000
1
2
5
23
<NULL>
<NULL>
<NULL>

EDIT: The purpose of getting null values to the bottom is to sort a set of data with the rows with null values placed at the bottom.

This is what I expect,

| Sample Input                  || Current output                || Expected output            |
|-------------------------------||-------------------------------||----------------------------|
| 2     0.9000      value 1     || 11               value 10     || 10  -23         value 9    |
| 3     23          value 2     || 4                value 3      || 14  -5          value 13   |
| 4                 value 3     || 8                value 7      || 13  -2          value 12   |
| 5     1           value 4     || 10   -23         value 9      || 12  -1          value 11   |
| 6     2           value 5     || 14   -5          value 13     || 9   -0.9000     value 8    |
| 7     5           value 6     || 13   -2          value 12     || 2   0.9000      value 1    |
| 8                 value 7     || 12   -1          value 11     || 5   1           value 4    |
| 9     -0.9000     value 8     || 9    -0.9000     value 8      || 6   2           value 5    |
| 10    -23         value 9     || 2    0.9000      value 1      || 7   5           value 6    |
| 11                value 10    || 5    1           value 4      || 3   23          value 2    |
| 12    -1          value 11    || 6    2           value 5      || 11              value 10   |
| 13    -2          value 12    || 7    5           value 6      || 4               value 3    |
| 14    -5          value 13    || 3    23          value 2      || 8               value 7    |
8
  • aren't you trying just to suppress the empty lines? should the non-numeric lines also be sorted?
    – user313992
    Commented Oct 16, 2018 at 11:18
  • I was thinking of a case where this would apply to data with multiple columns, whereas the other columns may contain data for the respective rows. Commented Oct 16, 2018 at 11:37
  • 1
    then you should use multiple -k options to sort; eg. sort -k 2r,2r -k 1g,1g file will first reverse sort lexicographically by the second column, then sub-sort by the first column in general-numeric order.
    – user313992
    Commented Oct 16, 2018 at 11:40
  • 1
    I just updated the question @sddgob Commented Oct 16, 2018 at 12:19
  • Yes, @Goro I'm looking for a way to get null values to the bottom when sorted in ascending order. Commented Oct 16, 2018 at 12:24

4 Answers 4

2

You might pipe the result through a suitable post-processor. Here's one I wrote in sed:

#!/bin/sed -f

# Move any null into hold space
/^$/{
H
d
}

# Insert nulls after last line
$G
# Delete an extra newline this introduces
$s/\n//

If your sort really writes <NULL> rather than a blank line, you'll need to change the /^$/ pattern to /^<NULL>$/.

Demo

sort -g <<EOF | ./475768.sed 
0.9000
23
      
1
2     
5
  
-0.9000
-23
 
-1
-2
-5
EOF
-23
-5
-2
-1
-0.9000
0.9000
1
2
5
23


 
1
  • +1. As one-liner: sort -g input.data | sed '/^$/{H;d;};$G;$s/\n//'
    – pLumo
    Commented Oct 16, 2018 at 12:58
1

sort -g input.data | grep [0-9] && grep -v [0-9] input.data

  1. Sort
  2. Filter only numbers
  3. Add remaining NULLs by inverting the grep command
1
  • 2
    please notice that the numbers may also have the form -1, .3, -.7, +0, -1e1 but not foo4 or catch22
    – user313992
    Commented Oct 16, 2018 at 11:18
0

You can use the flags V and r in sort as follows:

sort -Vr file
-23
-5
-2
-1
-0.9000
23
5
2
1
0.9000




 .

According to sort man:

 -r, --reverse               reverse the result of comparisons
 -V, --version-sort          natural sort of (version) numbers within text
0

With this sample input:

$ cat infile
 2     0.9000      value 1
 3     23          value 2
 4                 value 3
 5     1           value 4
 6     2           value 5
 7     5           value 6
 8                 value 7
 9     -0.9000     value 8
 10    -23         value 9
 11                value 10
 12    -1          value 11
 13    -2          value 12
 14    -5          value 13

Use this command:

$ sort -k 3n,3n -k 2g,2g infile

Which results in this output:

 10    -23         value 9
 14    -5          value 13
 13    -2          value 12
 12    -1          value 11
 9     -0.9000     value 8
 2     0.9000      value 1
 5     1           value 4
 6     2           value 5
 7     5           value 6
 3     23          value 2
 4                 value 3
 8                 value 7
 11                value 10

This is different from the Expected output from the answer in that the 11 value 10 line comes just at the end, instead of before the 4 value 3 line. Please update the question if there is a reason for a 11 < 4 < 8 or 10 < 3 < 7 ordering, or if it's more to the problem than the sample data suggests.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .