根据列中的值对文件内容进行子集化

根据列中的值对文件内容进行子集化

我有一个文本文件(例如):

apple   V$NFY_Q6_rc V=0.741
apple   V$HOXA7_01_rc   V=0.454
apple   V$ALPHACP1_01_rc    V=0.695
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q2_01 V=0.677
grapes  V$SP1_Q6_01_rc  V=0.685
grapes  V$SP1_Q6_rc V=0.884

我想提取每个水果具有最高 V 值(在第 3 列)的行。我的输出应该如下所示:

apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q6_rc V=0.884

我在不同的子目录中有几个这样的文件。

子集化后,我将使用以下代码来获取第 2 列中特定字符串出现的次数。

        perl -lanE '$str=$F[1];  $f="/home/$str/list/$str.txt"; $c=`grep -c "$str" "$f"`;chomp($c);$x=0;$x++ if $c;say "$str\t$x\t$c"' file2

这将产生以下输出。假设我正在该文件的第 2 列中搜索字符串“SP4”:

         X       X in file?  number of times it occurs
        NFA            0                            0
        SP4            1                            2
        NFATC1         0                            0

我想要 V 值(上面的值与此表一起包含在内)

          X       X in file?  number of times it occurs      V value
        NFA            0                            0
        SP4            1                            2         0.747
        NFATC1         0                            0

PS:关于中间的perl程序的更多详细信息,请参考这个链接:

         http://stackoverflow.com/questions/23109490/search-for-occurrence-of-a-string-in-another-file-in-a-particular-column

答案1

如果顺序不重要,两次传递sort就可以了。在第一遍中,按字段 1 排序,然后按字段 3 的数字部分(起始位置 4)进行反向排序。该-b修饰符会导致前导空格被忽略。将此管道传递给第二个sort,为字段 1 中的每个唯一值返回一条记录,但这次指定 stable sort( -s) 修饰符以确保字段 3 中具有最高值的记录(该记录已冒泡到每个值的顶部)在字段 1 中,返回先前的排序)

sort -k1,1 -k3.4b,3nr file.txt | sort -k1,1 -s -u
apple   V$NFY_Q6_rc V=0.741
grapes  V$SP1_Q6_rc V=0.884
orange  V$SP4_Q5    V=0.747

答案2

awk

awk -F'[ =]' '$NF>a[$1]{a[$1]=$NF;b[$1]=$0}END{for (i in b) print b[i]}' filename.txt

这是通过创建 V 值的数组 a 来实现的,该数组由第一列索引。对于每一行,将 V 值与该索引的数组的当前值进行比较,如果它更大,则更新数组中的值并将整行存储在第二个数组 b 中。处理完整个文件后,将打印 b 中的所有内容。

输出示例:

orange  V$SP4_Q5    V=0.747
apple   V$NFY_Q6_rc V=0.741
grapes  V$SP1_Q6_rc V=0.884

如果顺序很重要,您可以通过管道传输sort(例如,按 V 号排序):

awk -F'[ =]' '$NF>a[$1]{a[$1]=$NF;b[$1]=$0}END{for (i in b) print b[i]}' filename.txt | sort -t= -nk2

给出:

apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q6_rc V=0.884

工作示例:http://ideone.com/WPvRzh

答案3

这是一个解决方案perl

$ perl -F'\s+|=' -anle '
    $h{$F[0]} = [$F[-1],$_] if $F[-1] > $h{$F[0]}->[0];
    END {print $h{$_}->[1] for keys %h}' file
grapes  V$SP1_Q6_rc V=0.884
apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747

更新

假设运行两个单行代码后有两个结果。

file1:

apple   V$NFY_Q6_rc V=0.741
orange  V$SP4_Q5    V=0.747
grapes  V$SP1_Q6_rc V=0.884

file2:

X       X in file?  number of times it occurs
NFA            0                            0
SP4            1                            2
NFATC1         0                            0

你可以试试这个:

$ awk -F'[ =]+' 'FNR==NR{a[$2]=$NF;next}
            FNR==1{print $0"\tV value";next}
            {for(i in a){
                if(index(i,$1)){
                    print $0"\t"a[i];
                    next;
                }
            }
            print;
        }' file1 file2
X       X in file?  number of times it occurs   V value
NFA            0                            0
SP4            1                            2   0.747
NFATC1         0                            0

相关内容