1行に文字が表示される回数に基づいてファイルをソートする方法は?

1行に文字が表示される回数に基づいてファイルをソートする方法は?

私はLinuxに初めてアクセスし、ファイルで文字計算を実行する方法に関する多くの有用な情報を見つけましたが、Linux / Terminalに文字が表示される特定の回数でテキストファイルを並べ替える方法はありますか?ライン?

たとえば、次のようになります。

baseball
aardvark
a man a plan a canal panama
cat
bat
bill

文字「a」が表示される回数に基づいてソートすると、次のような結果が得られます。

a man a plan a canal panama
aardvark
baseball
cat
bat
bill

「a」がそれぞれ1回出現する「cat」と「bat」については、同じ数の行順が変わっても構いません。

答え1

これらの操作に対する一般的なアプローチは、awkまたはperl...を使用して関心のある指標を計算し、行の前に追加し、それをソートされた出力に提供し、ソートされた出力sortから測定項目を削除することです。

awk '{print gsub("a","a"), $0}' < file | sort -rn | cut -d' ' -f2-

答え2

別のSchwartz変換:

$ awk -Fa '{print NF,$0}' file | sort -nr | cut -d' ' -f2-
a man a plan a canal panama
aardvark
baseball
cat
bat
bill

またはPerlでは:

perl -Fa -lane 'print "$#F $_"' file | sort -nr | cut -d' ' -f2-

答え3

文字だけで並べ替えることもできます。

tr -cd a\\n <file | paste - ./file | LC_ALL=C sort -rk1,1 | cut -f2-

tr例は組み立て後、パイピング前の様子は次のとおりです。pastesort

aa  baseball
aaa aardvark
aaaaaaaaaa  a man a plan a canal panama
a   cat
a   bat
    bill

それからsortそれを取得し、すべてが同じであれば、より長いキーよりも短いキーをソートしますが、-rその逆の場合、出力は次のようになります。

aaaaaaaaaa  a man a plan a canal panama
aaa aardvark
aa  baseball
a   cat
a   bat
    bill

...cut最初のタブだけを削除してください。

a man a plan a canal panama
aardvark
baseball
cat
bat
bill

答え4

Schwartzian変換が言及されて以来、まだこれに対する純粋なPerlの実装を投稿した人がいないことに驚きました。

perl -ne 'push @a, $_ }{ print map { $_->[0] } sort { $b->[1] <=> $a->[1] } map { [$_, $_ =~ tr/a//] } @a' file
a man a plan a canal panama
aardvark
baseball
cat
bat
bill

ファイル内の各行はにプッシュされ、次にファイルを@a読み取ると、a文字数を使用して配列がソートされます。

文字数を数えることは計算コストのかかる関数ではないため、ソートのみを使用する方がきちんとしたアプローチです。

$ perl -ne 'push @a, $_ }{ print sort { $b =~ tr/a// <=> $a =~ tr/a// } @a' file
a man a plan a canal panama
aardvark
baseball
cat
bat
bill

関連情報