2

I need to sort a list like this one, by the first uppercase letter:

{alan turing Smith's Prize 1936}
{werner heisenberg Matteucci Medal 1929}
{albert einstein Barnard Medal 1920}

From the manual entry for :sort, I'd expect that any of those commands would accomplish that:

:sort /[^A-Z]*/ 
:sort /[A-Z]/ r
:sort /.\{-}\ze[A-Z]/

Instead, sorting is done on the first lowercase:

{alan turing Smith's Prize 1936}
{albert einstein Barnard Medal 1920}
{werner heisenberg Matteucci Medal 1929}

I noticed that if I capitalize the first word, then it sorts that first. As if the pattern only tried to match on the first word, instead of the whole line:

{Werner heisenberg Matteucci Medal 1929}
{alan turing Smith's Prize 1936}
{albert einstein Barnard Medal 1920}

What am I doing wrong here?

  • 1
    Welcome to Vi and Vim! Looks like you have 'ignorecase' enabled... You can check it with :set ic?. Without it being on, the first one you used (:sort /[^A-Z]*/) worked for me. – filbranden Nov 17 '20 at 18:19
  • 1
    @filbranden thats correct, I had ignorecase enabled. When I did set noignorecase and tried again, it worked. – Yuri Ghensev Nov 17 '20 at 19:36
  • 1
    I was going to suggest setting 'smartcase' together with 'ignorecase' (that's what I typically use), but I found that :sort doesn't seem to respect it... Filed a bug about it: github.com/vim/vim/issues/7322 – filbranden Nov 17 '20 at 23:41
3

The sort pattern is skipped, so you could use

sort /.\{-}\ze\u/

or

sort r /\u\+/

(the r should cause it sort on the matching parts.)

Importantly, any lines not matching are kept in order, but separated.


I recognize these are similar to what you tried (with \u instead of [A-Z]). For some reason, it actually made a difference for me. That is, using [A-Z] didn't work in either command, but \u did. Odd.

3

Commands such as :sort /[^A-Z]*/ to skip non-uppercase letters should typically work, except when 'ignorecase' is set, which makes that pattern case-insensitive and will skip characters other than any letters, be them uppercase or lowercase. From the comments, it looks like you do have 'ignorecase' enabled.

You might have the pattern /[^A-Z]*/ work correctly in a search to match non-uppercase letters (including lowercase ones), if in addition to 'ignorecase' you also have 'smartcase' enabled. Having both 'ignorecase' and 'smartcase' both enabled is a pretty common setup, since it's quite an useful combination. Make searches case-insensitive if you have all lowercase characters, but case-sensitive if you have any uppercase characters anywhere.

But it turns out that the :sort command recognizes the 'ignorecase' setting, but not the 'smartcase' setting! That's why you might see one behavior for patterns in search, but a subtly different one in sorts.

I opened an issue on the Vim issue tracker about this and the conclusion is that this is the intended behavior (or, if not initially defined this way on purpose, will be maintained as such to prevent breaking backwards compatibility.) A recent update to Vim runtimes included an update to the documentation to call this out explicitly, initially shipped with Vim version 8.2.2026. The updated documentation simply states that "'ignorecase' applies to the pattern, but 'smartcase' is not used."

In your case, you can use the suggestions from D. Ben Knoble's answer, such as :sort /.\{-}\ze\u/ or :sort r /\u\+/.

Another option is to use an explicit \C in your pattern, to force it to be case-insensitive, regardless of the 'ignorecase' setting:

:sort /\C[^A-Z]*/

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.