1

次の入力と出力を考慮します。

  infile   |   outfile
1 3 5 2 4  |  1 2 3 4 5
2 4 5      |  2 4 5
4 6 2 1    |  1 2 4 6

次のアプローチよりも高速にファイルの各行のエントリをソートする、プログラミング言語を含まないUNIX プログラムの組み合わせ(シェルスクリプト自体以外のもの) はありますか?

while read line; do
    tr ' ' '\n' <<< ${line} | sort | tr '\n' ' '
    echo ""
done < infile > outfile

つまり、そのための小さなプログラムを作成することはできますが、通常のワンライナーを使用して魔法のように問題を解決するcpp/python/awk/...のと同じではありません。

編集:

単に欲しいものを尋ねるのではなく、テキストを追加しすぎたに違いありません。率直に言って、上記のソリューションと同じくらいのオーバーヘッドなしで、行内のエントリを並べ替えることができる UNIX プログラム/プログラムの組み合わせ (パイプ、fors、whiles などを使用)があるかどうかを確認したかったのです。

perl、awk、python などのプログラミング言語で厄介な仕事をする可能性があることはわかっていますが、実際には、これらの言語インタープリターを使用しない UNIX プログラムの構成を探していました。答えから、そのようなツールはないと結論付けなければなりませんinline sort。私が得た解決策、主に非常にきちんとした Perl ワンライナーに非常に感謝しています。

それでも、私が投稿した Bash アプローチでこれほど多くのオーバーヘッドが発生する理由はよくわかりません。これは本当に多数のコンテキスト スイッチが原因なのか、それとも入力を前後に変換して並べ替えるだけのオーバーヘッドなのか?

これらのステップのどれが実行を非常に遅くしているのか理解できないようです。約 50 万行のファイル内のエントリを並べ替えるには数分かかり、各行には約 30 の値があります。

4

4 に答える 4

1
#!awk -f
{
  baz = 0
  PROCINFO["sorted_in"] = "@val_num_asc"
  split($0, foo)
  for (bar in foo)
    $++baz = foo[bar]
}
1

結果

1 2 3 4 5
2 4 5
1 2 4 6
于 2013-05-16T01:02:10.560 に答える
1

質問は見た目よりも微妙です。あなたはソートを実行するためのより迅速な方法があるかどうかを尋ねているようで、Perl や awk などで多くの (エレガントな!) 回答を得ています。しかし、あなたの質問は、 shell built-insを使用してより迅速にソートできるかどうかのようです。そのため、答えはノーです。

明らかに、sort はシェルの組み込みではなく、tr もそうではありません。sort が行うことを行うビルトインはなく、「tr」の代わりになる可能性のあるビルトインは、ここでは役に立たない可能性があります (たとえば、bash の IFS 変数を削除する操作には、同じくらいの作業が必要になります)。 tr と一緒に暮らすための tr への呼び出し)。

個人的には、Perl を使用します。あなたのデータセットが大きいかファンキーな場合、sort プラグマを使用して Perls のデフォルトのソートアルゴリズムを変更するオプションがあることに注意してください。整数のファイルをソートするために必要になるとは思いませんが、おそらくそれはあなたの側の単なる例でした.

于 2013-05-16T03:00:43.390 に答える
0

きれいではありません (間違いなくワンライナーではありません) が、組み込みのシェル コマンドのみを使用して行を並べ替えることができますが、短い行の場合は、外部関数を繰り返し呼び出すよりも高速な場合があります。

#!/bin/sh
sortline(){
for x in $@;do
    [ ! "$FIRST" ] && FIRST=t && set --
    i=0
    while [ $i -le $# ];do
        [ $x -lt $((${@:$((i+1)):1})) ] && break || i=$((i+1))
    done
    set -- ${@:1:$i}  $x   ${@:$((i+1)):$(($#-$i))}
done
echo $@
}
while read LINE || [ "$LINE" ];do
    sortline $LINE
done <$1 >$2

編集:ところで、これは誰かが疑問に思った場合の選択ソートアルゴリズムです

Edit2:これは数値のみです。文字列の場合は[ "$x" -lt "${@:$((i+1)):1}" ](チェックなし)のような比較を使用する必要がありますが、このCプログラムを文字列に使用します(単にqsortと呼びます)が、argvでatoiを使用して変更できます:

#include <stdlib.h>
#include <string.h>
static inline int cmp(const void *a, const void *b){
   return strcmp(*(const char **)a, *(const char **)b);
}

int main(int argc, char *argv[]){
    qsort(++argv, --argc, sizeof(char *), cmp);
    while (argc){
      write(1,argv[0],strlen(argv[0]));
      write(1,(--argc && argv++)?"\t":"\n",1);
   }
}
于 2013-05-16T03:01:09.280 に答える