我只写几行来 grep 文件中的最小值,它给了我正确的结果,但重复行两次可以修复错误
我在做什么:
- 查找所有文件
- 正在删除标头
- 使用第九列以科学记数法排序
- 使用 awk 排序并打印后取最小的第一行
- 我也想要打印 $i 的文件名
脚本:
#!/bin/bash
for i in `ls -v *.txt`
do
smallestPValue=`sed 1d $i | sort -k9 -g | head -1 | awk '{print $0}'`
echo $i $smallestPValue >> smallesttPvalueAll.txt
done
输出
U1.text 4 rsxxx 1672175 A ADD 759 0.0751 4.918 1.074e-06
U1.txt 4 rsxxxx 1672175 A ADD 759 0.0751 4.918 1.074e-06
U2.txt 16 rsxxxx 596342 T ADD 734 -0.05458 -5.204 2.535e-07
U2.txt 16 rsxxxx 596342 T ADD 734 -0.05458 -5.204 2.535e-07
U3.txt 2 rsxxxx 12426 T ADD 722 0.06825 5.285 1.669e-07
我得到了几行的重复,而有些则很好,因为上面的 U3 已经出现一次,这就是我想要的。我可以通过 uniq 或 sort -u 轻松删除重复的行,但只是好奇是什么原因造成的
所需输出每行重复一次
答案1
awk
如果我解释正确,你可能可以用and来做你想做的事情sort
- 不需要循环,或者解析 ls(微妙的提示:不要那样做!), 或head
或sed
.
awk 'FNR > 1 {print FILENAME, $0}' *.txt | sort -k10 -g | sort -u -k1,1
这会跳过每个文件的第一行,然后打印以文件名和空格(awk 的默认输出记录分隔符或ORS
)为前缀的所有剩余行。然后它通过排序对字段 10 进行通用数字排序。最后,它仅对第一个字段(文件名)进行唯一排序-k1,1
,以便仅输出具有该文件名的第一行。
请注意,我们必须在此处对字段 10 进行排序,而不是字段 9,因为我们已将文件名添加为第一个字段,因此所有其他字段编号都会增加 1。
FNR
和FILENAME
是内置 awk 变量。 FNR 是当前文件的行号(awk-lingo 中的“输入记录号”),FILENAME 是当前文件名。
这是另一种方法,这次仅使用awk
:
#!/usr/bin/awk -f
FNR > 1 && (! s[FILENAME] || $9 < s[FILENAME]) {
s[FILENAME]=$9;
l[FILENAME]=$0
};
END {
for (f in s) {
print f, l[f]
}
}
将其另存为,例如smallest-pvalue.awk
,使其可执行chmod +x smallest-pvalue.awk
并运行为./smallest-pvalue.awk *.txt
。
此 awk 脚本在名为 的数组中跟踪每个输入文件的字段 9 的最小值,s
并将匹配的输入行保存在 array 中l
。
处理完所有文件后,它会打印出文件名和包含每个文件的最小第 9 个字段的行。