Bash:基于另一列的值获取一列的值
我有一个以空间分隔的文件,其中包含:Bash:基于另一列的值获取一列的值,bash,sorting,awk,unix-head,Bash,Sorting,Awk,Unix Head,我有一个以空间分隔的文件,其中包含: 5.75e-01 7.00e-1 5.52e-01 7.33e-01 ./dir1/dir2/file1.csv 5.75e-01 7.00e-1 5.42e-01 7.34e-01 ./dir1/dir2/file2.csv 5.75e-01 7.00e-1 5.72e-01 7.43e-01 ./dir2/dir2/file1.csv 5.75e-01 7.00e-1 5.22e-01 7.23e-01 ./dir2/dir2/file2.csv 5.7
5.75e-01 7.00e-1 5.52e-01 7.33e-01 ./dir1/dir2/file1.csv
5.75e-01 7.00e-1 5.42e-01 7.34e-01 ./dir1/dir2/file2.csv
5.75e-01 7.00e-1 5.72e-01 7.43e-01 ./dir2/dir2/file1.csv
5.75e-01 7.00e-1 5.22e-01 7.23e-01 ./dir2/dir2/file2.csv
5.75e-01 7.00e-1 5.02e-01 7.93e-01 ./dir3/dir2/file1.csv
5.75e-01 7.00e-1 5.12e-01 7.63e-01 ./dir3/dir2/file2.csv
我想提取第5列的值,该值对应于第3列中dir#的每个值的最大值。例如,假设我说的是dir1
。对应于这些行的:
5.75e-01 7.00e-1 5.52e-01 7.33e-01 ./dir1/dir2/file1.csv
5.75e-01 7.00e-1 5.42e-01 7.34e-01 ./dir1/dir2/file2.csv
我可以通过以下方式找到这些:
max_val_acc_=$(awk '$5 ~ /dir1/ { print }' filename.txt)
echo $max_val_acc
现在我想我需要将这个结果通过排序
,然后取头
,但我无法让它工作。我要寻找的结果(对于dir1
)是:
/dir1/dir2/file1.csv
以及所有dir#的完整结果:
我不确定我是否正确理解你,但这就是我理解你的方式:
awk -v s="dir1" ' # search parameter in your s
index($5,"./" s "/") { # if your s is found in $5
if(max==""||$3>max){ # we initialize $3 or compare to previous max
max=$3; # store new max
maxv=$5 # and new mac value
}
}
END{ print maxv } # print the stored max value
' file # oh just the file
./dir1/dir2/file1.csv
这就是你要找的吗
$ cat tst.awk
{
split($5,path,"/")
dir = path[2]
if ( !(dir in max) || ($3 > max[dir]) ) {
max[dir] = $3
val[dir] = $5
}
}
END {
for (dir in val) {
print val[dir]
}
}
$ awk -f tst.awk file
./dir3/dir2/file2.csv
./dir1/dir2/file1.csv
./dir2/dir2/file1.csv
另一种选择是
sort
和awk
$ sort -k5 -k3,3r file | awk -F/ '!a[$NF]++'
5.75e-01 7.00e-1 5.52e-01 7.33e-01 ./dir1/dir2/file1.csv
5.75e-01 7.00e-1 5.42e-01 7.34e-01 ./dir1/dir2/file2.csv
以上是文件名,如果基于第一个目录名
$ sort -k3,3r file | awk '{split($NF,d,"/")} !a[d[2]]++'
5.75e-01 7.00e-1 5.72e-01 7.43e-01 ./dir2/dir2/file1.csv
5.75e-01 7.00e-1 5.52e-01 7.33e-01 ./dir1/dir2/file1.csv
5.75e-01 7.00e-1 5.12e-01 7.63e-01 ./dir3/dir2/file2.csv
如果你只想打印目录
$ sort -k3,3r file | awk '{split($NF,d,"/")} !a[d[2]]++{print $NF}'
./dir2/dir2/file1.csv
./dir1/dir2/file1.csv
./dir3/dir2/file2.csv
只是为了好玩-没有任何(
awk
,perl
之类)编程语言
file="./data.txt"
paste -d ' ' "$file" <(cut -d/ -f2 "$file") |\
LC_ALL=C sort -k6 -k3gr | uniq -f5 | cut -d' ' -f5
使用一些awk解决方案。正如我所说,这只是为了显示另一种方式。虽然与您请求的输出不匹配,并且与已经发布的其他答案类似,但我发现这个awk命令更令人难忘:
< file | sort -k3,3r | awk -F "/" '!seen[$2]++'
更一般的一点是:按大小对整个列表进行排序(第3列),不必担心按目录名对其进行排序(第5列的一部分),然后提取每个目录名的第一个(即,awk只打印新看到的键名)
如果确实希望仅输出目录名称和排序,请将以下内容添加到管道链:
| cut -d ' ' -f5- | sort
在进行最小/最大比较时,始终使用读取的第一个值作为种子,而不是希望所有输入值都为正值。另外,用
s=“dir2”
试试,你会看到它失败了,因为dir2
出现在每一行上(你需要将它设为索引($0,“./“s”/”)
或类似的值)。如果两个dir具有相同的max$3值,那么输出应该是什么?3r做什么?我理解-k3是按第3列排序的,但我阅读了排序手册页,仍然不理解-k3,3r
< file | sort -k3,3r | awk -F "/" '!seen[$2]++'
5.75e-01 7.00e-1 5.72e-01 7.43e-01 ./dir2/dir2/file1.csv
5.75e-01 7.00e-1 5.52e-01 7.33e-01 ./dir1/dir2/file1.csv
5.75e-01 7.00e-1 5.12e-01 7.63e-01 ./dir3/dir2/file2.csv
| cut -d ' ' -f5- | sort