【问题标题】:Output calculations from multiple files to a single multi-column file using awk使用 awk 将计算从多个文件输出到单个多列文件
【发布时间】:2020-02-18 15:01:48
【问题描述】:

我想知道是否有办法将单个文件作为输出,其中每列都有一些从多个文件中获取的计算数字。 我的意见是:

@SRR1544694.1 Run0199_AC237YACXX_L2_T1101_C27 length=52
AGTAAAGGGACTCGGTCTCCTTCCATTGGAGGTTGTTTTCTAGGCTCAACAC
+SRR1544694.1 Run0199_AC237YACXX_L2_T1101_C27 length=52 
?;=ADDDDF@C3ACE:E?FED+CF>AABGFFB:?10?:BDDFB?@3BFFEEF 
@SRR1544694.2 Run0199_AC237YACXX_L2_T1101_C28 length=52
TTGATAGGGGAGATGCTAGCAAAAAGGTGTACTTCTCAGCGGAGCAGAAAGA
+SRR1544694.2 Run0199_AC237YACXX_L2_T1101_C28 length=52
CCCFFFFFHHHHHIHIGHIIIGGIHII?DGHIIIIIIEHCHIIIIIIHIHHI 
@SRR1544694.3 Run0199_AC237YACXX_L2_T1101_C54 length=52
TTTTTGGGGGGGAATTCTCTTGCTTCAACAATAACGTCTCTTTCAGAAGGCA

目的是计算 ATGC 行(第二行和每 4 行)中 G 和 C 元素的百分比。真实文件将有数百万行。 预期的输出应该是:

File1   File2
48.0769 48.0769   
46.1538 46.1538 
42.3077 42.3077 
32.6923 32.6923  
51.9231 51.9231  
42.3077 42.3077    

我已经尝试了下面的代码。它将在特定行中完成的计算输出到与每个原始文件匹配的单个文件。如果未定义输出,它将打印一列。

awk '
FNR==1{   # first record of an input file?
  if(o)close(o);   # was previous output file? close it
  o=FILENAME;sub(/\.fastq/,"_sorted.txt",o)   # new output file name
}
{
  if(NR%4==2){n=length($1); gc=gsub("[gcGC]", "", $1); print gc/n*100 >o}
}
' *.fastq 

我想知道是否有一种方法,使用 awk(尤其是学习工具)将所有计算放在一个文件中,列分隔。

【问题讨论】:

  • 欢迎来到 SO,您能否在您的帖子中发布示例输入和预期输出,然后让我们知道。
  • 是的,有办法。如果您需要更多信息,请edit您的问题提供简洁、可测试的样本输入和预期输出。

标签: bash awk


【解决方案1】:

使用以下内容我重新创建了输入文件:

cat >1.fastq <<EOF
@SRR1544694.1 Run0199_AC237YACXX_L2_T1101_C27 length=52
AGTAAAGGGACTCGGTCTCCTTCCATTGGAGGTTGTTTTCTAGGCTCAACAC
+SRR1544694.1 Run0199_AC237YACXX_L2_T1101_C27 length=52 
?;=ADDDDF@C3ACE:E?FED+CF>AABGFFB:?10?:BDDFB?@3BFFEEF 
@SRR1544694.2 Run0199_AC237YACXX_L2_T1101_C28 length=52
TTGATAGGGGAGATGCTAGCAAAAAGGTGTACTTCTCAGCGGAGCAGAAAGA
+SRR1544694.2 Run0199_AC237YACXX_L2_T1101_C28 length=52
CCCFFFFFHHHHHIHIGHIIIGGIHII?DGHIIIIIIEHCHIIIIIIHIHHI 
@SRR1544694.3 Run0199_AC237YACXX_L2_T1101_C54 length=52
TTTTTGGGGGGGAATTCTCTTGCTTCAACAATAACGTCTCTTTCAGAAGGCA
EOF

cat >2.fastq <<EOF
@SRR1544694.1 Run0199_AC237YACXX_L2_T1101_C27 length=52
AGTAAAGGGACTCGGTCTCCTTCCATTGGAGGTTGTTTTCTAGGCTCAACAC
+SRR1544694.1 Run0199_AC237YACXX_L2_T1101_C27 length=52
?;=ADDDDF@C3ACE:E?FED+CF>AABGFFB:?10?:BDDFB?@3BFFEEF
@SRR1544694.2 Run0199_AC237YACXX_L2_T1101_C28 length=52
TTGATAGGGGAGATGCTAGCAAAAAGGTGTACTTCTCAGCGGAGCAGAAAGA
+SRR1544694.2 Run0199_AC237YACXX_L2_T1101_C28 length=52
CCCFFFFFHHHHHIHIGHIIIGGIHII?DGHIIIIIIEHCHIIIIIIHIHHI
@SRR1544694.3 Run0199_AC237YACXX_L2_T1101_C54 length=52
TTTTTGGGGGGGAATTCTCTTGCTTCAACAATAACGTCTCTTTCAGAAGGCA
EOF

以下带有 cmets 的脚本:

# print the headers
printf "%s\n" *.fastq | paste -sd' '
# merge all files
paste *.fastq |
# for each line for each the field print the counts
awk 'NR % 4 == 2{
        for (i = 1; i <= NF; ++i) {
                n = length($i); gc = gsub("[gcGC]", "", $i); res = gc/n*100
                printf res (i == NF ? "\n" : "\t")
        }
}' "$i"

将生成以下输出(两个文件相同,只是为了说明它的工作原理):

1.fastq 2.fastq
48.0769 48.0769
46.1538 46.1538
42.3077 42.3077

我没有修改计算百分比背后的逻辑,只是修改了结果的合并方式。

我把我的其他尝试留在下面:

或者使用以下脚本,使用paste 而不是awk 折叠结果:

output=""
for i in *.fastq; do
        output=$(
                printf "%s\n" "$output" | 
                # merge line-wise output with another results
                paste - <(
                        echo "$i"
                        awk '{ if(NR%4==2){n=length($1); gc=gsub("[gcGC]", "", $1); print gc/n*100} }' "$i"
                )
        )
done
# in output theere will be leading tabs
# remove them
output=$(printf "%s" "$output" | cut -f2-)

echo "$output"

如果真的有数百万行和文件,使用临时文件作为paste 输出而不是将其存储在变量中将节省大量内存。

或者,它可以逐行生成所有结果,然后例如使用 awk script from stackoverflow 转置输出:

for i in *.fastq; do
        printf "%s" "$i"
        awk '{ if(NR%4==2){n=length($1); gc=gsub("[gcGC]", "", $1); printf " " gc/n*100} }' "$i"
        echo
done |
awk '
{ 
    for (i=1; i<=NF; i++)  {
        a[NR,i] = $i
    }
}
NF>p { p = NF }
END {    
    for(j=1; j<=p; j++) {
        str=a[1,j]
        for(i=2; i<=NR; i++){
            str=str" "a[i,j];
        }
        print str
    }
}'

【讨论】:

  • 嗨,卡米尔!到目前为止,我一直在测试您的第二个解决方案,将 awk 放在 paste 命令中。它真的很好用!!我也会尝试最后一个,并会尽快更新。存储在变量中的工作不应该比使用临时文件更快吗?我没有任何内存或 CPU/磁盘限制。
  • storing in a variable work faster than with a temp file - 更快,是的。更多的内存消耗 - 也是。该文件可以足够大,以耗尽您的内存。所以对于非常大的文件,你可以使用临时文件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-30
  • 2023-03-14
  • 1970-01-01
  • 2021-05-16
  • 2014-12-08
相关资源
最近更新 更多