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    |
  • aren't you trying just to suppress the empty lines? should the non-numeric lines also be sorted? – mosvy Oct 16 '18 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. – Ishan Madhusanka Oct 16 '18 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. – mosvy Oct 16 '18 at 11:40
  • 1
    I just updated the question @sddgob – Ishan Madhusanka Oct 16 '18 at 12:19
  • Yes, @Goro I'm looking for a way to get null values to the bottom when sorted in ascending order. – Ishan Madhusanka Oct 16 '18 at 12:24
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. As one-liner: sort -g input.data | sed '/^$/{H;d;};$G;$s/\n//' – pLumo Oct 16 '18 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
  • 2
    please notice that the numbers may also have the form -1, .3, -.7, +0, -1e1 but not foo4 or catch22 – mosvy Oct 16 '18 at 11:18
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.