使用 ANSI 转义码对字符串进行排序

使用 ANSI 转义码对字符串进行排序

我正在尝试打印所有 zsh 选项的排序列表,其中设置选项颜色为绿色,未设置选项颜色为红色。不过,我无法sort在彩色线上正常工作。下面打印所有红色选项,然后打印所有绿色选项:

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

我认为这是因为print -P正在扩展格式字符串,以便每个选项行以^[[31m红色和^[[32m绿色开头。看着sort联机帮助页,我看到两个可能有帮助的选项:

-i, --ignore-nonprinting 仅考虑可打印字符

-k, --key=POS1[,POS2] 在 POS1(起始点 1)处开始一个键,在 POS2 处结束(默认行尾)

所以我尝试:

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

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

我尝试设置<N>许多不同的数字。在所有情况下,我都得到了相同的结果(所有红色选项都在绿色之前)。我该如何解决这个问题?

答案1

-ksort 选项采用两个数字参数:字段和字符。您想要对第一个字段的第 6 个字符进行排序。它是第 6 个字符,因为%F{green}被 替换ESC[32m。所以这应该有效:

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

答案2

在像 之类的转义序列中^[[31m,转义字符^[是非打印字符,但其他字符[31m是打印字符。所以sort -i不会帮助你:它忽略转义字符,但仍然[31mred[0m在 之前排序[32mgreen[0m

根据超出实用程序内置功能的标准对数据进行排序的通用方法sort是将每行上的数据加倍,对其进行处理,以便第一个副本是排序键,对行进行排序,最后剥离第一部分。例如,假设您要排序的数据不包含制表符:

awk '{s=$0; gsub(/\033\[[ -?]*[@-~]/,"",s); print s "\t" $0}' |
sort |
awk 'BEGIN {RS="\t"} {print $2}'

相关内容