Sorting strings with ANSI escape codes

colorsescape-characterssortzsh

I am trying to print a sorted list of all zsh options, with set options colored green and unset options colored red. I cannot get sort to work properly with on the colored lines though.The below prints all the red options followed by all the green options:

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort

I figured this was because print -P is expanding the format strings such that each option line starts with ^[[31m for red and ^[[32m for green. Looking at the sort manpage, I saw two options that might help:

-i, –ignore-nonprinting
consider only printable characters

-k, –key=POS1[,POS2]
start a key at POS1 (origin 1), end it at POS2 (default end of line)

So I tried:

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort -i

and

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort --key=<N>

Where I tried setting <N> to many different numbers. In all cases, I got the same results (all red options before all green). How can I solve this?

Best Answer

-k option of sort takes two numerical arguments: field and character. You want to sort on 6th character of first field. It is 6th character because %F{green} is replaced by ESC[32m. So this should work:

print -lP "%F{green}"${^$(setopt)} "%F{red}"${^$(unsetopt)} | sort -k 1.6
Related Question