0

我有一个空格分隔的文件,其中包含:

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 列的值,该值对应于 dir# 的每个值的第 3 列的最大值。例如,假设我在谈论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

现在我想我需要通过 a 传递这个结果sort并获取head,但我无法让它工作。我正在寻找的结果(对于dir1)是:

./dir1/dir2/file1.csv

以及所有目录的完整结果#:

./dir1/dir2/file1.csv
./dir2/dir2/file1.csv
./dir3/dir2/file2.csv
4

5 回答 5

1

这是你要找的吗?

$ 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
于 2017-03-16T17:29:07.710 回答
0

我不确定我对你的理解是否正确,但这就是我理解你的方式:

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
于 2017-03-16T17:19:33.993 回答
0

只是为了好玩 - 没有任何 ( awk, perllike) 编程语言

file="./data.txt"
paste -d ' ' "$file" <(cut -d/ -f2 "$file") |\
    LC_ALL=C sort -k6 -k3gr | uniq -f5 | cut -d' ' -f5

输出

./dir1/dir2/file1.csv
./dir2/dir2/file1.csv
./dir3/dir2/file2.csv

使用一些 awk 解决方案。正如我所说,这只是为了展示另一种方式。

于 2017-03-16T21:15:50.830 回答
0

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
于 2017-03-16T18:52:42.840 回答
0

虽然与您请求的输出不匹配并且与已经发布的其他答案类似,但我发现这个 awk 命令更令人难忘:

< 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

更一般的一点是:按大小对整个列表进行排序(第 3 列),不要担心按目录名称排序(第 5 列的一部分),然后提取每个目录名称的第一个(即 awk 仅打印新看到的键姓名)。

如果您真的希望输出只是目录名称并排序,则将以下内容添加到管道链中:

| cut -d ' ' -f5- | sort
于 2017-03-16T21:35:11.807 回答