假设我有一个包含文件_b
, a
, c
, č
,的目录d
。我想根据 cs_CZ.UTF8 语言环境对文件进行排序,但是没有忽略下划线,即像这样:_b a c č d
。
目前,ls
(ls | sort
也)像这样对文件进行排序:a _b c č d
.我找到的所有答案都建议使用LC_COLLATE=C
,但这会将顺序更改为:(_b a c d č
请注意,č
现在位于末尾,而不是在c
和之间,d
因为它应该是)。
有什么办法可以实现这个目标吗?
请注意,我还关心除下划线之外的其他字符,即我想a-n.pdf a-p.pdf a.pdf c č d
按此顺序排序而不是a-n.pdf a.pdf a-p.pdf c č d
。 (编辑:实际上,a.pdf a-n.pdf a-p.pdf c č d
也可以,只要不忽略非字母数字字符。)
以下不是我正在寻找的答案:
LC_COLLATE=C
如上所述使用,- 使用 shell 扩展,例如
ls _*; ls [^_]*
因为问题不仅仅是关于下划线。
答案1
在 GNU 系统上,将 NUL 附加到非 alpha 可能会有所帮助:
$ ls | sed 's/[^[:alpha:]]/&\x0/g' | sort | tr -d '\0'
_b
a
c
č
d
假设文件名不包含换行符。通常,您无法对文件名列表进行排序,sort
因为文件名本身很可能由多行组成。
在排序之前,您可以将文件名中的换行符替换为/
此处。和zsh
:
print -rNC1 -- *(N) | # print NUL-delimited
tr '\n\0' '/\n' |
sed 's/[^[:alpha:]]/&\x0/g' |
sort |
tr -d '\0' |
tr '/' '\n'
或者将列表保留为 NUL 分隔,以便可以对其进行后处理:
print -rNC1 -- *(N) | # print NUL-delimited
tr '\n\0' '/\n' |
sed 's/[^[:alpha:]]/&\x0/g' |
sort |
tr -d '\0' |
tr '/\n' '\n\0'
strcoll()
用于排序的 API 采用两个以 NUL 结尾的字符串。传统sort
实现仅支持文本输入,并且文本输入排除了 NUL,因此它们没问题。然而, GNUsort
与大多数标准文本实用程序的 GNU 实现一样,确实支持 NUL 及其输入。
我不知道 GNU 究竟如何sort
处理带有 NUL 的行,但我的猜测是它会打破 NUL 上的行并将段一对一进行比较。所以,举例来说,foo_\0car
比较时,先比较,再比较。foobar_\0more
foo_
foobar_
zsh
您还可以使用带有oe
(o
rder 基于e
某些代码的评估)或o+function
glob 限定符的任意转换来定义 glob 的顺序。但在打电话之前strcoll()
,zsh
删除 NUL,因此您不能使用与sort
上面的 GNU 相同的转换。
相反,您可以0
在非 alpha 序列之前添加 s,1
在 alpha 序列之前添加 s:
在~/.zshrc
set -o extendedglob
mysort() {
REPLY=${REPLY//(#m)[^[:alpha:]]##/0$MATCH}
REPLY=${REPLY//(#m)[[:alpha:]]##/1$MATCH}
}
然后:
$ print -rC1 -- *(No+mysort)
_b
a
c
č
d