bash在通过一对文件迭代大约3600万行之后返回错误的结果 – 这是内存错误吗?

我在bash中编写了一个简单的脚本来遍历一对文本文件,以确保它们的格式正确。

所需格式如下:

  • 每个文件包含数以百万计的“logging”。
  • 每个logging在每个文件中占用两行 – 一个标题行和一个序列行。
  • 每个标题行由一个“>”符号组成,后跟一个样本名称(字母数字string),后跟一个句点,后跟一个唯一的logging标识号(一个整数),后跟一个后缀'/ 1'或' / 2' 。
  • 每个序列行包含30-100个A,C,G和T字符(四个DNA核苷酸,如果有人想知道的话)的string。
  • 这些文件是成对的,因为一个文件中的第一个logging对应于第二个文件中的第一个logging,依此类推。 两个文件中的标题行应该是相同的,除了在一个文件中它们将全部具有“/ 1”siffix,在另一个文件中它们将具有“/ 2”后缀。 两个文件之间的序列行可能非常不同。

我开发的代码旨在检查(a)每个logging中的听众行遵循正确的格式,(2)两个文件中相应logging中的标题行匹配(即除/ 1和/ 2后缀)和(c)序列行只包含A,C,G和T字符。

格式正确的logging示例:

> cat -n file1 | head -4 1 >SRR573705.1/1 2 ATAATCATTTGCCTCTTAAGTGGGGGCTGGTATGAATGGCAAGACGGGAATCTAGCTGTCTCTCCCTTATATCTTGAAGTTAATATTTCTGTGAAGAAGC 3 >SRR573705.2/1 4 CCACTTGTCCCAGTCTGTGCTGCCTGTACAATGGATTAGCTGAGGAAAACTGGCATCCCATGGCCTCAAACAGACGCAGCAAGTCCATGAAGCCATAATT > cat –n file2 | head -4 1 >SRR573705.1/2 2 TTTCTAACAATTGAATTAGCAACACAAACACTATTGACAAAGCTATATCTTATTTCTACTAAAGCTCGATAGGGTCTTCTCGTCCTGCGATCCCATTCCT 3 >SRR573705.2/2 4 GTATGATGGGTGTGTCAAGGAGCTCAACCATCGTGATAGGCTACCTCATGCATCGAGACAAGATCACATTTAATGAGGCATTTGACATGGTCAGGAAGCA 

我的代码如下。 对于只包含几百条logging的小型testing文件来说,它效果很好。 但是,在读取包含数百万或logging的实际数据文件时,它将返回无意义的错误,例如:

 Inaccurate header line in read 18214236 of file2 Line 36428471: TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC 

上面的错误是完全错误的。 file2的36,428,471行是'> SRR573705.19887618 / 2'

错误中报告的string甚至不在文件2中。但是,它在file1中出现多次,即:

 cat -n /file1 | grep 'TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC' 4632838 TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC 24639990 TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC 36428472 TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC 143478526 TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC 

这两个文件中的数据似乎完全匹配错误返回的区域:

 cat -n file1 | head -36428474 | tail 36428465 >SRR573705.19887614/1 36428466 CACCCCAGCATGTTGACCACCCATGCCATTATTTCATGGTATTTTCTTACATTTTGTATATAACAGATGCATTACGTATTATAGCATTGCTTTTCGTAAA 36428467 >SRR573705.19887616/1 36428468 AGATCCTCCTCCTCATCGGTCAGTCGCCAATCCAACAACTCAACCTTCTTCTTCAAGTCACTCAGCCGTCGGCCCGGGACTGCCGTTTCATGATGCCTAT 36428469 >SRR573705.19887617/1 36428470 CAATAGCGTATATTAAAATTGCTGCAGTTAAAAAGCTCGTAGTTGGATCTTGGGCGCAGGCTGGCGGTCCGCCGCAAGGCGCGCCACTGCCAGCCTGGCC 36428471 >SRR573705.19887618/1 36428472 TGATTTCCTCCATAAGTGCCTTCTCGCACTCAACATCTTGATCACTACGTTCCTCAGCATTCGCCTCTTCTTCTTCTTCCTGTTCCTTTTTTTCATCCTC 36428473 >SRR573705.19887619/1 36428474 CCAGCCTGCGCCCAAGATCCAACTACGAGCTTTTTAACTGCAGCAATTTTAATATACGCTATTGGAGCTGGAATTACCGCGGCTGCTGGCACCAGACTTG >cat -n file2 | head -36428474 | tail 36428465 >SRR573705.19887614/2 36428466 GTAATTTACAGGAATTGTTTACATTCTGAGCAAATAAAACAAATAATTTTAATACACAAACTTGTTGAAAGTTAATTAGGTTTTACGAAAA 36428467 >SRR573705.19887616/2 36428468 GCCGTCGCAGCAACATTTGAGATATCCCGTAAGACGTCTTGAACGGCTGGCTCTGTCTGCTCTCGGAGAACCTGCCGGCTGAACCGGACAGCGCAGACG 36428469 >SRR573705.19887617/2 36428470 CTCGAGTTCCGAAAACCAACGCAATAGAACCGAGGTCCTATTCCATTATTCCATGCTCTGCTGTCCAGGCGGTCGGCCTG 36428471 >SRR573705.19887618/2 36428472 GGACATGGAAACAGAAAATAATGAAAAGACCAAAGAAGATGCACTTGAGGTTGATAAGCCTAAAGG 36428473 >SRR573705.19887619/2 36428474 CCCGACACGGGGAGGTAGTGACGAAAAATAGCAATACAGGACTCTTTCGAGGCCCTGTAATTGGAATGAGTACACTTTAAATCCTTTAACGAGGATCTAT 

在bash中是否有某种内存限制会导致这样的错误? 我已经在多个文件上运行这个代码的各种版本,并且在36,000,000行之后始终得到这个问题。

我的代码:

 set -u function fastaConsistencyChecker { F_READS=$1 R_READS=$2 echo -e $F_READS echo -e $R_READS if [[ ! -s $F_READS ]]; then echo -e "File $F_READS could not be found."; exit 0; fi if [[ ! -s $R_READS ]]; then echo -e "File $R_READS could not be found."; exit 0; fi exec 3<$F_READS exec 4<$R_READS line_iterator=1 read_iterator=1 while read FORWARD_LINE <&3 && read REVERSE_LINE <&4; do if [[ $(( $line_iterator % 2 )) == 1 ]]; then ## This is a header line ## if [[ ! ( $FORWARD_LINE =~ ^">"[[:alnum:]]+\.[0-9]+/1$ ) ]]; then echo -e "Inaccurate header line in read ${read_iterator} of file ${F_READS}" echo -e "Line ${line_iterator}: ${FORWARD_LINE}" exit 0 fi if [[ ! ( $REVERSE_LINE =~ ^">"[[:alnum:]]+\.[0-9]+/2$ ) ]]; then echo -e "Inaccurate header line in read ${read_iterator} of file ${R_READS}" echo -e "Line ${line_iterator}: ${REVERSE_LINE}" exit 0 fi F_Name=${FORWARD_LINE:1:${#FORWARD_LINE}-3} R_Name=${REVERSE_LINE:1:${#REVERSE_LINE}-3} if [[ $F_Name != $R_Name ]]; then echo -e "Record names do not match. " echo -e "Line ${line_iterator}: ${FORWARD_LINE}" echo -e "Line ${line_iterator}: ${REVERSE_LINE}" exit 0 fi line_iterator=$(( $line_iterator + 1 )) else if [[ ! ( $FORWARD_LINE =~ ^[ATCGNatcgn]+$ ) ]]; then echo -e "Ambigous sequence detected for read ${read_iterator} at line ${line_iterator} in file ${F_READS}" exit 0 fi read_iterator=$(( $read_iterator + 1 )) line_iterator=$(( $line_iterator + 1 )) fi unset FORWARD_LINE unset REVERSE_LINE done echo -e "$line_iterator lines and $read_iterator reads" echo -e "No errors detected." echo -e "" } export -f fastaConsistencyChecker FILE3="filepath/file1" FILE4="filepath/file2" fastaConsistencyChecker $FILE3 $FILE4 

我认为你已经证明有一个与内存使用bash相关的问题。 我认为你可以通过使用bash中的文本处理工具来完成你的格式验证而不会遇到内存问题。

 #!/bin/bash if ! [[ $1 && $2 && -s $1 && -s $2 ]]; then echo "usage: $0 <file1> <file2>" exit 1 fi set -e dir=`mktemp -d` clean () { rm -fr $dir; } trap clean EXIT pairs () { sed 'N;s/\n/\t/' "$@"; } pairs $1 > $dir/$1 pairs $2 > $dir/$2 paste $dir/$1 $dir/$2 | grep -vP '^>(\w+\.\d+)/1\t[ACGT]+\t>\1/2\t[ACGT]+$' && exit 1 exit 0 

sed脚本占用一行,并与下一行连接,由制表符分隔。 这个:

 >SRR573705.1/1 ATAATCATTTGCCTCTT... 

变成这样:

 >SRR573705.1/1 ATAATCATTTGCCTCTT... 

粘贴文件1的第一行和文件2的第一行,并将它们输出为由制表符分隔的一行。 它对第二行也是这样,等等。 grep看到这样的输入:

 >SRR573705.1/1. ATAATCATTTGCCTCT.... >SRR573705.1/2. TTTCTAACAATTGAAT... 

正则表达式捕获第一个标识符,并在稍后与反向引用\1中的行匹配相同的标识符。

由于-v切换到grep,脚本输出的任何行都不匹配正则表达式。 如果输出行,则脚本以状态1退出。