列/行の長さに基づいてファイルを並べ替える

列/行の長さに基づいてファイルを並べ替える

最初の列の文字数に基づいてファイルを並べ替える必要があります。

私は何をすべきかわかりません。 (Linuxではsed / awk / sortを使用できます。)

一例:

.abs is bla bla 12
.abc is bla se 23 bla
.fe is bla bla bla
.jpg is pic extension
.se is for swedish domains

私が望むのは、各行の最初の列の長さに基づいて行をソートすることです。一部の行は4文字で始まり、一部の行は3〜2文字で始まります。私は結果が次のようになりたいと思います:

.fe is bla bla bla
.se is for swedish domains
.abs is bla bla 12
.abc is bla se 23 bla
.jpg is pic extension

可能ですか?

答え1

awkまず、を使用して文字数を含む他の列を追加してから、追加されたsort列を削除できます。

awk '{printf "%d %s\n", length($1), $0}' file.txt | sort -n -k1,1 | sed -E -e 's/^[0-9]+ //'

答え2

デフォルトのシェルツールを使用して実行できます。ただし、Perlを使用すると、要件をより直接的に表現できます。

perl -l -e 'print sort {@a = split(/ /, $a, 2); @b = split(/ /, $b, 2);
                        length($a[0]) <=> length($b[0])} <>'

とともにシュワルツ変換(一括入力でより効率的):

perl -l -e 'print map {$_->[0]}
                  sort {length($a->[1]) cmp length($b->[1])}
                  map {[$_, split(/ /, $_, 2)]} <>'

Pythonを使用している場合、コードはより冗長ですが、より明確です。

python -c 'import sys;
lines = sys.stdin.readlines();
lines.sort(key=lambda line: len(line.split()[0]));
sys.stdout.writelines(lines)'

答え3

$ awk -vOFS='\t' '{ print length($1), $0 }' file.in | sort -k1,1n -k2,2 | cut -f2-
.fe is bla bla bla
.se is for swedish domains
.abc is bla se 23 bla
.abs is bla bla 12
.jpg is pic extension

これにより、最初の列のデータ長に基づいてファイルがソートされ、最初の列の実際のデータfile.inがアルファベット順に並べ替えられます(質問では特に要求されませんが、結果をうまく処理できます)。

このawkコードは、次のようにタブ区切りの出力を生成します。

4       .abs is bla bla 12
4       .abc is bla se 23 bla
3       .fe is bla bla bla
4       .jpg is pic extension
3       .se is for swedish domains

これはsort最初の列(数字順)でソートされ、次に2列目(事前順)でソートされます。次に、cut最初の列を削除します。

関連情報