首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用自定义排序顺序对Unix中的字母数字字符串进行排序

使用自定义排序顺序对Unix中的字母数字字符串进行排序
EN

Stack Overflow用户
提问于 2017-01-23 10:41:43
回答 5查看 2K关注 0票数 3

我有一个名单,名单上的名字是不正常的。如何使用字母部分的自定义排序顺序,使它们符合正确的字母数字顺序?

我的文件numbers.txt

代码语言:javascript
复制
alpha-1
beta-3
alpha-10
beta-5
alpha-5
beta-1
gamma-7
gamma-1
delta-10
delta-2

主要的一点是,我的脚本应该认识到,它应该在beta之前打印beta,在gamma之前打印beta,在delta之前打印gamma

也就是说,单词应该根据它们所代表的希腊字母的顺序进行排序。

预期订单:

代码语言:javascript
复制
alpha-1
alpha-5
alpha-10
beta-1
beta-3
beta-5
gamma-1
gamma-7
delta-2
delta-10

PS:我试过用sort -n numbers.txt,但它不符合我的需要。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2017-01-23 15:23:37

您可以使用辅助awk命令,如下所示:

代码语言:javascript
复制
awk -F- -v keysInOrder="alpha,beta,gamma,delta" '
    BEGIN {
        split(keysInOrder, a, ",")
        for (i = 1; i <= length(a); ++i) keysToOrdinal[a[i]] = i
    }
    { print keysToOrdinal[$1] "-" $0 }
' numbers.txt | sort -t- -k1,1n -k3,3n | cut -d- -f2-
  • awk命令用于:
代码语言:javascript
复制
- map the custom keys onto numbers that reflect the desired sort order; note that the full list of keys must be passed via variable `keysInOrder`, in order.
- prepend the numbers to the input as an auxiliary column, using separator `-` too; e.g., `beta-3` becomes `2-beta-3`, because `beta` is in position _2_ in the ordered list of sort keys.

  • 然后,sort根据映射的数字和第二列中的原始数字对awk的输出进行排序,得到所需的自定义排序顺序。
  • 然后cut移除辅警。又是映射数字。
票数 2
EN

Stack Overflow用户

发布于 2017-01-23 15:24:00

我想在这里找到Perl。此脚本将起作用:

代码语言:javascript
复制
#!/usr/bin/env perl
use v5.14;          # turn on modern features

# Greek alphabet
my @greek_letters =qw(alpha beta     gamma   delta epsilon zeta
                      eta   theta    iota    kappa lambda  mu
                      nu    xi       omicron pi    rho     sigma
                      tau   upsilon  phi     chi   psi     omega);

# An inverted map from letter name to position number;
# $number{alpha} = 1, $number{beta} = 2, etc:
my %number;
@number{@greek_letters} = 1..@greek_letters;

# Read the lines to sort
chomp(my @lines = <>);

# split on hyphen into arrays of individual fields
my @rows = map { [ split /-/ ] } @lines;

# prepend the numeric position of each item's Greek letter
my @keyed = map { [ $number{$_->[0]}, @$_ ] } @rows;

# sort by Greek letter position (first field, index 0) and then
# by final number (third field, index 2)
my @sorted = sort {   $a->[0] <=> $b->[0]
                   || $a->[2] <=> $b->[2] } @keyed;

# remove the extra field we added
splice(@$_, 0, 1) for @sorted;

# combine the fields back into strings and print them out
say join('-', @$_) for @sorted;

将Perl代码保存到一个文件(例如,greeksort.pl)中,并运行perl greeksort.pl numbers.txt以获得排序的输出。

票数 1
EN

Stack Overflow用户

发布于 2017-01-23 16:16:04

这里有一个Python解决方案。不要试图用Bash,sed,awk来做困难的事情。您通常可以完成您想要的,但它将更加混乱,更容易出错,更难维护。

代码语言:javascript
复制
#!/usr/bin/env python3

# Read input lines
use_stdin = True
if use_stdin:
    import sys
    lines = sys.stdin.read().strip().split()
else:
    # for testing
    with open('numbers.txt') as input:
        lines = input.read().strip().split()

# Create a map from greek letters to integers for sorting
greek_letters = """alpha beta     gamma   delta epsilon zeta
                   eta   theta    iota    kappa lambda  mu
                   nu    xi       omicron pi    rho     sigma
                   tau   upsilon  phi     chi   psi     omega"""
gl = greek_letters.strip().split()
gl_map = {letter:rank for rank, letter in enumerate(gl)}

# Split each line into (letter, number)
a = (x.split('-') for x in lines)
b = ((s, int(n)) for s,n in a)

# Using an order-preserving sort, sort by number, then letter
by_number = lambda x: x[1]
by_greek_letter = lambda x: gl_map.get(x[0])
c = sorted(sorted(b, key=by_number), key=by_greek_letter)

# Re-assemble and print
for s,n in c:
    print('-'.join((s, str(n))))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41804397

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档