Subject: Re: bug#22084: Potential Bug in sort -r

From: Eric Blake <[email-masked]>
Date: Thu, 3 Dec 2015 10:19:36 -0700

tag 22084 notabug
thanks

On 12/03/2015 05:30 AM, Adrià Rovira wrote:
> Dear GNU,
> 
> I am using the sort command in  (GNU coreutils) version 8.13
> 
> I noticed the reverse option is not correctly applied if it has to sort by
> more than one column.
> 
> This behaviour is corrected by forcing again the type of sort.
> 
> This happens with -n and -g.
> 
> Example:
> 
> echo -e "930 7.83\n930 77.52\n930 54.09" | sort -n -k1 -k2r

First, a couple of notes:

'echo -e' is not portable; you should consider using printf(1) instead.

Then, you are not specifying the keys you thought.  Let's look at this
with sort's --debug option:

$ printf '930 7.83\n930 77.52\n930 54.09\n' | sort -n -k1 -k2r --debug
sort: using ‘en_US.UTF-8’ sorting rules
sort: key 1 is numeric and spans multiple fields
sort: leading blanks are significant in key 2; consider also specifying 'b'
930 7.83
___
   _____
________
930 77.52
___
   ______
_________
930 54.09
___
   ______
_________

You probably want to use the -k1,1 notation and an explicit -b to ensure
that your field usage is sane:

$ printf '930 7.83\n930 77.52\n930 54.09\n' | sort -n -k1,1 -k2b,2r --debug
sort: using ‘en_US.UTF-8’ sorting rules
930 7.83
___
    ____
________
930 77.52
___
    _____
_________
930 54.09
___
    _____
_________

Now, on to your actual report.  Here is what 'info sort' says:

   A position in a sort field specified with ‘-k’ may have any of the
option letters ‘MbdfghinRrV’ appended to it, in which case no global
ordering options are inherited by that particular field.  The ‘-b’
option may be independently attached to either or both of the start and
end positions of a field specification, and if it is inherited from the
global options it will be attached to both.  If input lines can contain
leading or adjacent blanks and ‘-t’ is not used, then ‘-k’ is typically
combined with ‘-b’ or an option that implicitly ignores leading blanks
(‘Mghn’) as otherwise the varying numbers of leading blanks in fields
can cause confusing results.

Or, referring to POSIX:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sort.html

    The keydef argument is a restricted sort key field definition. The
format of this definition is:

    field_start[type][,field_end[type]]

    where field_start and field_end define a key field restricted to a
portion of the line (see the EXTENDED DESCRIPTION section), and type is
a modifier from the list of characters 'b', 'd', 'f', 'i', 'n', 'r'. The
'b' modifier shall behave like the -b option, but shall apply only to
the field_start or field_end to which it is attached. The other
modifiers shall behave like the corresponding options, but shall apply
only to the key field to which they are attached; they shall have this
effect if specified with field_start, field_end, or both. If any
modifier is attached to a field_start or to a field_end, no option shall
apply to either.

So the moment you add 'r' to a particular -k, that key is no longer
benefiting from the global -n option, and you are correct that you then
have to re-specify 'n' on a per-'-k' basis, as you did here:

> echo -e "930 7.83\n930 77.52\n930 54.09" | sort -n -k1 -k2rn
> 930 77.52
> 930 54.09
> 930 7.83

Since this is the documented behavior, and matches the POSIX
requirement, there is no bug.  I'm thus closing out this report;
however, feel free to add further comments to the thread.

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org