行ごとの単語数で行を並べ替える


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。2つの行が同じ数の単語を共有している場合は、タイをアルファベット順にすることを好みますが、それは要件ではありません。
カレブ徐

回答:


22

次のようなことができます:

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

awk各行のフィールド数にプレフィックスを付けるために使用します。次にsort、その番号で、で削除しcutます。


これはうまくいきました。なぜ順序が逆になったのか疑問に思っていましたが、私は今あなたの編集を見ています。
カレブ徐

6

最近のGNU では、配列要素を印刷する順序(elementによって制御される)など、配列を使用して多くの内部パラメーターを定義awkできます。したがって、の値でインデックスを作成し、配列を作成できます。どの要素がの値を持ち、目的の出力に出力します。PROCINFO"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

これにより、2番目のソートキーとして単語をソートするのではなく、同じフィールド数のレコード間の元の順序が保持されるようになりました。キーがの場合、フォールバック/複製処理メカニズムとして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="")
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.