按每行字数对行进行排序


14

给定输入:

hello: world foo bar baz
bar:
baz: bin boop bop fiz bang beep
bap: bim bam bop
boatkeeper: poughkeepsie

我想将其排序为顶部的大多数单词,至少是末尾的单词,如下所示:

baz: bin boop bop fiz bang beep
hello: world foo bar baz
bap: bim bam bop
boatkeeper: poughkeepsie
bar:

我将如何使用sort其他工具执行此操作?


为了清楚起见,您想按单词数排序而不是按行长排序(在您的示例输入中,单词数最多的行也是最长的,但并非总是如此)?
don_crissti

是。总的来说,字数最多的行不一定最长。例如,我想bin: bop boop之前boatkeeper: poughkeepsie。如果两行共享相同数量的单词,我希望按字母顺序将关系按字母顺序排列,但这不是必须的。
Caleb Xu

Answers:


22

您可以执行以下操作:

awk '{print NF,$0}' file | sort -nr | cut -d' ' -f 2-

我们使用awk前缀为每行添加字段数。然后sort,我们用该数字删除并用删除cut


这工作了。想知道为什么订单被撤消,但是现在看到您的修改。
Caleb Xu

6

在最近的GNU中,awk可以使用PROCINFO数组定义许多内部参数,包括打印数组元素的顺序(由element控制"sorted_in")。因此,我们可以使用的值构建和索引数组NF" "NR,其中元素具有的值$0并将其打印在所需的输出中,在您的情况下为"@ind_num_desc"

awk '{a[NF" "NR]=$0}END{PROCINFO["sorted_in"]="@ind_num_desc"; for(i in a) print a[i]}' file

1
+1在想着同样的事情:不过,也许有人应该注意,这会带来重复删除输入的
副作用

@steeldriver,您绝对正确,我编辑了答案,现在应该可以了。
jimmij 2015年

现在,这将保留具有相同字段数的记录之间的原始顺序,而不是将单词作为辅助排序键进行排序。如果您的密钥是NF" "$0" "NR,则您只能将其NR作为后备/重复处理机制。
彼得·科德斯

1
@PeterCordes,但这会颠倒单词的顺序,除按定义自己的功能外,我看不到按字母顺序解决关系的方法-gnu cmp_func()awk允许这样做。
jimmij

5

Perl一线:

print sort { split(' ',$a) <=> split(' ',$b) } <>;

如果您想使用字母顺序打破平局:

print sort { split(' ',$a) <=> split(' ',$b) or $a cmp $b } <>;

4

通过python。

s = '''hello: world foo bar baz
bar:
baz: bin boop bop fiz bang beep
bap: bim bam bop'''.splitlines()
for i in sorted(s, key=lambda x: len(x.split()), reverse=True):
    print(i)

要么

with open('/path/to/the/input/file') as f:
    m = f.readlines()
    for i in sorted(m, key=lambda x: len(x.split()), reverse=True):
        print(i, end="")
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.