我在bash中编写了一个简单的脚本来遍历一对文本文件,以确保它们的格式正确。
所需格式如下:
我开发的代码旨在检查(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退出。