次のようなファイル1があります
25 104.601 0.5
24.8488 104 0.5
24.5341 103 0.5
24.1844 102 0.5
24.1568 101 0.5
24.1568 100 0.5
24.1844 99 0.5
24.5341 98 0.5
列 1 から最小値を見つけて別のファイルに印刷する必要があります_NEW
ここで、異なるファイルに対して上記を繰り返し、少なくとも 100 個のファイルの最小値を見つける必要があります。
こうすることで、file_NEWに次のような最終出力が出力されます。
24.1568
23.3254 (from file2)
22.312 (from file3)
.....
ここで、file2とfile3はfile1と同様のデータセットを持っています。すべての入力ファイルはfile*.txtのような同じ名前パターンを持ち、同じディレクトリにあります。
awk または sed でこれを行う方法を提案できる人はいますか?
ありがとう
答え1
最小値を見つけるには、以下のコマンドを使用します。
各ファイルに対して以下のコマンドを使用します
awk 'NR==1{sum=$1}($1 < sum){sum=$1}END{print sum}' filename >> outputfile
テスト済みで問題なく動作しました
答え2
awk '{print $1 "\t(from " FILENAME ")"}' file* | sort -k1,1n | awk -F'\t' '!seen[$2]++'
上記は、標準的な UNIX ツールを使用して、すべての入力ファイルに対して一度に堅牢かつ効率的に動作します。例:
$ cat file1
25 104.601 0.5
24.8488 104 0.5
24.5341 103 0.5
24.1844 102 0.5
24.1568 101 0.5
24.1568 100 0.5
24.1844 99 0.5
24.5341 98 0.5
$ cat file2
75 104.601 0.5
74.8488 104 0.5
74.5341 103 0.5
74.1844 102 0.5
74.1568 101 0.5
74.1568 100 0.5
74.1844 99 0.5
74.5341 98 0.5
$ awk '{print $1 "\t(from " FILENAME ")"}' file{1,2} | sort -k1,1n | awk -F'\t' '!seen[$2]++'
24.1568 (from file1)
74.1568 (from file2)
ただし、ファイル名にタブ文字や改行文字が含まれていないことを前提としています。タブが含まれている場合は、簡単な調整で処理できます。
awk '{print $1 "\t(from " FILENAME ")"}' file* |
sort -k1,1n |
awk '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
\0
ただし、改行も含まれている場合は、 (NUL) 終端文字に対応するために GNU ツールが必要になります。
awk -v ORS='\0' '{print $1 "\t(from " FILENAME ")"}' file* |
sort -z -k1,1n |
awk -v RS='\0' '{f=$0; sub(/[^\t]*\t/,"",f)} !seen[f]++'
答え3
バージョンsed
find . -name "file*" -exec sh -c '
echo $(sort -nk1 "$1" | sed -n "1{s/ .*//p}" )" (from "${1##*/}")" ' sh {} \; | sort -nk1 > output.txt; cat output.txt
sort
必要に応じて出力ファイルを編集し、ファイル名を追加する
答え4
私の理解では、各ファイルにこれが必要です:
awk 'NF' FILE | sort -n -k1 - | awk 'NR==1{print $1}' >> file_NEW
awk 'NF' FILE
入力ファイルに空白行がある場合、先頭にが必要です。このコマンドを特定のディレクトリ内のすべてのファイルに対して再帰的に実行するか、非再帰的に実行するか、または名前に特定のパターンを持つ一部のファイルに対してのみ実行するかを指定しませんでした。とにかく、find
次のようにして実行できます。
find . -name "FILE*" -exec sh -c 'awk "NF" FILE | sort -n -k1 - | awk "NR==1{print \$1}" >> file_NEW' sh {} \;
この場合、上記のコマンドは、指定されたディレクトリ内で名前が で始まるすべてのファイルに対して実行されますFILE
。
また、これは、見つかった各ファイルに対して以降のすべてを盲目的に実行するfile_NEW
ので、必ずしも出力にソートされたリストが生成されるわけではないことに注意してください。find
-exec