python - 使 python 排序/比较与 GNU 排序相同

标签 python bash shell sorting

似乎经过一些初步测试,Python 使用与 Linux 排序(gnu 排序)相同的排序顺序和 C 排序顺序(如果语言环境设置为“C”)。

但是我希望能够编写 Python 代码,根据语言环境使用与 gnu 排序相同的方式进行排序和比较。

说明问题的小示例代码:

import os 
import subprocess

words = [
    "Abd",
    "éfg",
    "aBd",
    "aBd",
    "zzz",
    "ZZZ",
    "efg",
    "abd",
    "fff",
    ]

with open("tosort", "w") as fout:
    for word in words:
        fout.write(word + "\n")

os.environ["LC_ALL"] = "en_US.UTF-8" 
proc = subprocess.Popen(["sort", "tosort"], stdout=subprocess.PIPE)
sort_en_utf = proc.stdout.read().decode('utf-8').split()

os.environ["LC_ALL"] = "C" 
proc = subprocess.Popen(["sort", "tosort"], stdout=subprocess.PIPE) 
sort_c = proc.stdout.read().decode('utf-8').split()

os.environ["LC_ALL"] = "en_US.UTF-8"
sort_py = sorted(words)

for row in zip(sort_en_utf, sort_c, sort_py):
    print(" ".join(row))

如果运行上面的代码,我会得到以下输出:

abd Abd Abd
aBd ZZZ ZZZ
aBd aBd aBd
Abd aBd aBd
efg abd abd
éfg efg efg
fff fff fff
zzz zzz zzz
ZZZ éfg éfg

第 1 列是排序/比较顺序,如果语言环境是“en_US.UTF-8”,我希望在我的 python 代码中使用第 2 列和第 3 列显示,python 的排序方式与 linux 的排序方式相同,如果语言环境设置为“C”。

所以我也想知道是否有办法:

"éfg" < "fff"产量为真。我不坚持使用比较运算符,我也可以调用函数。 但排序结果应考虑当前语言环境。

最佳答案

嗯,不知怎的,我忽略了这一点:

python排序文档https://docs.python.org/3.5/howto/sorting.html在最后一节“Odds and Ends”中提到函数 locale.strxfrm()(参见 https://docs.python.org/3.5/library/locale.html#locale.strxfrm)作为排序的关键函数,locale.strcoll() 作为比较函数。

所以下面的修改代码几乎OK,除了比较函数不直接返回true/false,但是在我的上下文中这是OK

import subprocess

words = [
    "Abd",
    "éfg",
    "aBd",
    "aBd",
    "zzz",
    "ZZZ",
    "efg",
    "abd",
    "fff",
    "sra",
    "ssa",
    "ssb",
    "stb",
    "ßaa",
    ]

val1 = "ßaa"
val2 = "ssb"

with open("tosort", "w") as fout:
    for word in words:
        fout.write(word + "\n")

os.environ["LC_ALL"] = "en_US.UTF-8"
proc = subprocess.Popen(["sort", "tosort"], stdout=subprocess.PIPE)
sort_en_utf = proc.stdout.read().decode('utf-8').split()

os.environ["LC_ALL"] = "C"
proc = subprocess.Popen(["sort", "tosort"], stdout=subprocess.PIPE)
sort_c = proc.stdout.read().decode('utf-8').split()

locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
sort_py1 = sorted(words, key=lambda v: locale.strxfrm(v))
print("%r < %r = %s , but locale.strcoll(%r, %r) = %s for %s"
      % (val1, val2, val1 < val2, val1, val2,
         locale.strcoll(val1, val2), locale.getlocale())
      )

locale.setlocale(locale.LC_ALL, "C")
sort_py2 = sorted(words, key=lambda v: locale.strxfrm(v))
print("%r < %r = %s , but locale.strcoll(%r, %r) = %s for %s"
      % (val1, val2, val1 < val2, val1, val2,
         locale.strcoll(val1, val2), locale.getlocale())
      )

for row in zip(sort_en_utf, sort_py1, sort_c, sort_py2):
    print(" ".join(row))

输出将是

'ßaa' < 'ssb' = False , but locale.strcoll('ßaa', 'ssb') = -1 for ('en_US', 'UTF-8')
'ßaa' < 'ssb' = False , but locale.strcoll('ßaa', 'ssb') = 1 for (None, None)
abd abd Abd Abd
aBd aBd ZZZ ZZZ
aBd aBd aBd aBd
Abd Abd aBd aBd
efg efg abd abd
éfg éfg efg efg
fff fff fff fff
sra sra sra sra
ssa ssa ssa ssa
ßaa ßaa ssb ssb
ssb ssb stb stb
stb stb zzz zzz
zzz zzz ßaa ßaa
ZZZ ZZZ éfg éfg

关于python - 使 python 排序/比较与 GNU 排序相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58192898/

相关文章:

shell - 联机帮助页标题中 shell 命令名称后面的括号中的数字有何含义?

linux - 如果写出从1到4321的数字,数字 '5'会出现多少次?

unix - unix中子进程的nohup

异步函数完成后的Python调用回调

python - 将csv.DictReader对象转换为非iter类型数据并按键合并值

python - 从 Pandas 数据框中删除不需要的值

regex - grep 和替换只能工作一半

python - IEEE 754 中公式失败的概率

bash - 将字符串添加到文件开头,将另一个字符串添加到文件末尾

linux - 如何在包含/bin 路径但不包含 shbangs 的目录中查找文件?