我有一个 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
我需要找到第 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]++'
但如果它们还包含换行符,那么您需要 GNU 工具来容纳\0
(NUL) 终止符:
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
IIUC,您希望每个文件都这样:
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