如何编写一个for循环来合并bash中所有第n列的文件



在代码的第二行中,我试图按列合并所有*.out.tab文件。代码的第三行提取第一列和随后的每一列(第4列、第8列、第12列、第16列…),即每个文件的每四列。

如果没有for循环,它就像。。。

paste 1.out.tab 2.out.tab 3.out.tab 4.out.tab 
awk '{for(i=1;i<=NF;i+=4){printf "%s ",$i;} print ""}' | 
tail -n +5 > tmpfile
cat tmpfile | sed "s/^ENSG*//" >gene_count.txt

但是,现在我想使用for循环来合并所有文件。

for f in `./alignments/repaired_reads/*ReadsPerGene.out.tab | sed 's/.ReadsPerGene.out.tab//'`;
paste "$f".out.tab | 
awk '{for(i=1;i<=NF;i+=4){printf "%s ",$i;} print ""}' | 
tail -n +5 > tmpfile
cat tmpfile | sed "s/^ENSG*://" > gene_count.txt

样本输入:

head ./alignments/repaired_reads/SRR9200814ReadsPerGene.out.tab
N_unmapped  18517   18517   18517
N_multimapping  1620    1620    1620
N_noFeature 8046    33145   33275
N_ambiguous 5860    1201    1034
ENSG00000160072 0   0   0
ENSG00000279928 0   0   0
ENSG00000228037 0   0   0
ENSG00000142611 0   0   0
ENSG00000284616 0   0   0
ENSG00000157911 0   0   0
head ./alignments/repaired_reads/SRR9200815ReadsPerGene.out.tab
N_unmapped  124416  124416  124416
N_multimapping  19165   19165   19165
N_noFeature 40924   384454  392595
N_ambiguous 99220   21834   20712
ENSG00000160072 0   0   0
ENSG00000279928 0   0   0
ENSG00000228037 0   0   0
ENSG00000142611 35  22  13
ENSG00000284616 0   0   0
ENSG00000157911 24  22  8

期望输出:

N_unmapped   18517  124416
N_multimapping   1620  19165
N_noFeature     33275  392595
N_ambiguous  1034  20712
ENSG00000160072     0  0
ENSG00000279928  0  0
ENSG00000228037  0  0
ENSG00000142611  0  13
ENSG00000284616  0  0
ENSG00000157911  0  8

使用您显示的示例和尝试,请尝试以下awk代码。这将确保$1的订单(第一个字段)与他们的存在相同。这将创建名为gene_count.txt的输出文件,并将读取多个文件作为输入。

awk '
!presence[$1]++{
arr[++max]=$1
}
{
for(i=4;i<=NF;i+=4){
maxValue[$1]=(maxValue[$1]>$i?maxValue[$1]:$i)
}
overAllMax[$1]=(overAllMax[$1]?overAllMax[$1] OFS:"") maxValue[$1]
}
END{
for(j=1;j<=max;j++){
print arr[j],overAllMax[arr[j]]
}
}
' *ReadsPerGene.out.tab > gene_count.txt

解释:添加对上述代码的详细解释。

  • 使用一个名为presence、索引为$1的数组,并检查其是否不存在,然后在其中创建一个条目,然后:
  • 创建一个名为arr的数组,该数组的索引为max变量,其值递增,并将值分配给arr作为$1
  • 开始for循环,每行每4、8、12和每4个字段一次
  • 创建一个名为maxValue的数组,索引为$1,并在此仅保留MAX值。仅通过使用三元运算符检查条件
  • 创建一个名为overAllMax的数组,它将有所有类似的第一个字段,所有的最大值都会不断附加到它后面,以基本上获得整体的最大值
  • 在该程序的END块中,从1一直到max的值,打印所有值
  • arr[j]的内循环打印值(即$1)和overAllMax[arr[j]]的值(即所有文件的每$1的最大值)

假设:

  • 根据第一列的内容连接多个文件
  • 所有文件在第一列中都有相同的行数和相同的值集

一种awk方法:

awk '
FNR==NR { lines[++max]=$1 }                                      # lines[] used to maintain ordering of input rows (based on first file)
{ for (i=4;i<=NF;i+=4)                                   # loop through 4th, 8th, 12th, ... columns
rec[$1]= rec[$1] (rec[$1]=="" ? "" : OFS) $i       # append to the record for this particular 1st column
}
END     { for (i=1;i<=max;i++)                                   # loop through indices of lines[] array
print lines[i],rec[lines[i]]                       # print 1st column and associated rec[] entry
}
' ./alignments/repaired_reads/*ReadsPerGene.out.tab > gene_count.txt

注意:

  • lines[]数组的唯一用途是允许我们维护输入行的顺序(从第一个文件开始)
  • OP的当前sed脚本从第一列的开头删除了ENSG字符串,但这并没有反映在预期输出中;现在我将忽略此操作

这会生成:

$ cat gene_count.txt
N_unmapped 18517 124416
N_multimapping 1620 19165
N_noFeature 33275 392595
N_ambiguous 1034 20712
ENSG00000160072 0 0
ENSG00000279928 0 0
ENSG00000228037 0 0
ENSG00000142611 0 13
ENSG00000284616 0 0
ENSG00000157911 0 8

这可能对你有用(GNU sed):

sed -E 's/^(S+)(s+(S+))*/1 3/
H
x
s/((nS+) [^n]*)((n[^n]*)*)2([^n]*)$/153/
x
$!d
x
s/.//' *.out.tab

将每行缩减为第一列和最后一列。

将当前行附加到保留空间。

切换到保留空间。

将先前复制的行的最后一列附加到其匹配行,并连接第一列。

切换回图案空间。

删除除最后一行以外的所有行。

在最后一行交换到保留空间。

删除第一个字符(这是H命令引入的换行符)。

打印结果。

相关内容

  • 没有找到相关文章

最新更新