将带有任意换行符的文本重新格式化为等长的行

Reformat text with arbitrary newlines into rows of equal length

抱歉,这可能是一个非常基本的问题 - 看起来应该很简单,但我就是想不通。

我正在尝试编写一个函数,给定一个带有任意间隔换行符的字母字符流(实际上,这意味着原始或 FASTA 格式的核苷酸序列),生成一个流,它在以下方面是相同的内容,但每五十个字符换行一次。也就是说,如果我向它提供以下输入(E.coli U 5/41 的 16S rRNA 基因序列与 FASTA 兼容的行长度):

AGTTTGATCATGGCTCAGATTGAACGCTGGCGGCAGGCCTAACACATGCAAGTCGAACGGTAACAGGAAG
CAGCTTGCTGCTTTGCTGACGAGTGGCGGACGGGTGAGTAATGTCTGGGAAACTGCCTGATGGAGGGGGA
TAACTACTGGAAACGGTAGCTAATACCGCATAACGTCGCAAGCACAAAGAGGGGGACCTTAGGGCCTCTT
GCCATCGGATGTGCCCAGATGGGATTAGCTAGTAGGTGGGGTAACGGCTCACCTAGGCGACGATCCCTAG
CTGGTCTGAGAGGATGACCAGCAACACTGGAACTGAGACACGGTCCAGACTCCTACGGGAGGCAGCAGTG
GGGAATATTGCACAATGGGCGCAAGCCTGATGCAGCCATGCNGCGTGTATGAAGAAGGCCTTCGGGTTGT
AAAGTACTTTCAGCGGGGAGGAAGGGAGTAAAGTTAATACCTTTGCTCATTGACGTTACCCGCAGAAGAA
GCACCGGCTAACTCCGTGCCAGCAGCCGCGGTAATACGGAGGGTGCAAGCGTTAATCGGAATTACTGGGC
GTAAAGCGCACGCAGGCGGTTTGTTAAGTCAGATGTGAAATCCCCGGGCTCAACCTGGGAACTGCATCTG
ATACTGGCAAGCTTGAGTCTCGTAGAGGGGGGTAGAATTCCAGGTGTAGCGGTGAAATGCGTAGAGATCT
GGAGGAATACCGGTGGCGAAGGCGGCCCCCTGGACGAAGACTGACGCTCAGGTGCGAAAGCGTGGGGAGC
AAACAGGATTAGATACCCTGGTAGTCCACGCCGTAAACGATGTCGACTTGGAGGTTGTGCCCTTGAGGCG
TGGCTTCCGGANNTAACGCGTTAAGTCGACCGCCTGGGGAGTACGGCCGCAAGGTTAAAACTCAAATGAA
TTGACGGGGGCCGCACAAGCGGTGGAGCATGTGGTTTAATTCGATGCAACGCGAAGAACCTTACCTGGTC
TTGACATCCACGGAAGTTTTCAGAGATGAGAATGTGCCTTCGGGAACCGTGAGACAGGTGCTGCATGGCT
GTCGTCAGCTCGTGTTGTGAAATGTTGGGTTAAGTCCCGCAACGAGCGCAACCCTTATCCTTTGTTGCCA
GCGGTCCGGCCGGGAACTCAAAGGAGACTGCCAGTGATAAACTGGAGGAAGGTGGGGATGACGTCAAGTC
ATCATGGCCCTTACGACCAGGGCTACACACGTGCTACAATGGCGCATACAAAGAGAAGCGACCTCGCGAG
AGCAAGCGGACCTCATAAAGTGCGTCGTAGTCCGGATTGGAGTCTGCAACTCGACTCCATGAAGTCGGAA
TCGCTAGTAATCGTGGATCAGAATGCCACGGTGAATACGTTCCCGGGCCTTGTACACACCGCCCGTCACA
CCATGGGAGTGGGTTGCAAAAGAAGTAGGTAGCTTAACTTCGGGAGGGCG

以下输入(连续序列):

AGTTTGATCATGGCTCAGATTGAACGCTGGCGGCAGGCCTAACACATGCAAGTCGAACGGTAACAGGAAGCAGCTTGCTGCTTTGCTGACGAGTGGCGGACGGGTGAGTAATGTCTGGGAAACTGCCTGATGGAGGGGGATAACTACTGGAAACGGTAGCTAATACCGCATAACGTCGCAAGCACAAAGAGGGGGACCTTAGGGCCTCTTGCCATCGGATGTGCCCAGATGGGATTAGCTAGTAGGTGGGGTAACGGCTCACCTAGGCGACGATCCCTAGCTGGTCTGAGAGGATGACCAGCAACACTGGAACTGAGACACGGTCCAGACTCCTACGGGAGGCAGCAGTGGGGAATATTGCACAATGGGCGCAAGCCTGATGCAGCCATGCGCGTGTATGAAGAAGGCCTTCGGGTTGTAAAGTACTTTCAGCGGGGAGGAAGGGAGTAAAGTTAATACCTTTGCTCATTGACGTTACCCGCAGAAGAAGCACCGGCTAACTCCGTGCCAGCAGCCGCGGTAATACGGAGGGTGCAAGCGTTAATCGGAATTACTGGGCGTAAAGCGCACGCAGGCGGTTTGTTAAGTCAGATGTGAAATCCCCGGGCTCAACCTGGGAACTGCATCTGATACTGGCAAGCTTGAGTCTCGTAGAGGGGGGTAGAATTCCAGGTGTAGCGGTGAAATGCGTAGAGATCTGGAGGAATACCGGTGGCGAAGGCGGCCCCCTGGACGAAGACTGACGCTCAGGTGCGAAAGCGTGGGGAGCAAACAGGATTAGATACCCTGGTAGTCCACGCCGTAAACGATGTCGACTTGGAGGTTGTGCCCTTGAGGCGTGGCTTCCGGATAACGCGTTAAGTCGACCGCCTGGGGAGTACGGCCGCAAGGTTAAAACTCAAATGAATTGACGGGGGCCGCACAAGCGGTGGAGCATGTGGTTTAATTCGATGCAACGCGAAGAACCTTACCTGGTCTTGACATCCACGGAAGTTTTCAGAGATGAGAATGTGCCTTCGGGAACCGTGAGACAGGTGCTGCATGGCTGTCGTCAGCTCGTGTTGTGAAATGTTGGGTTAAGTCCCGCAACGAGCGCAACCCTTATCCTTTGTTGCCAGCGGTCCGGCCGGGAACTCAAAGGAGACTGCCAGTGATAAACTGGAGGAAGGTGGGGATGACGTCAAGTCATCATGGCCCTTACGACCAGGGCTACACACGTGCTACAATGGCGCATACAAAGAGAAGCGACCTCGCGAGAGCAAGCGGACCTCATAAAGTGCGTCGTAGTCCGGATTGGAGTCTGCAACTCGACTCCATGAAGTCGGAATCGCTAGTAATCGTGGATCAGAATGCCACGGTGAATACGTTCCCGGGCCTTGTACACACCGCCCGTCACACCATGGGAGTGGGTTGCAAAAGAAGTAGGTAGCTTAACTTCGGGAGGGCG

— 它应该输出以下内容(相同的序列,每 50 characters/bases 换行):

AGTTTGATCATGGCTCAGATTGAACGCTGGCGGCAGGCCTAACACATGCA
AGTCGAACGGTAACAGGAAGCAGCTTGCTGCTTTGCTGACGAGTGGCGGA
CGGGTGAGTAATGTCTGGGAAACTGCCTGATGGAGGGGGATAACTACTGG
AAACGGTAGCTAATACCGCATAACGTCGCAAGCACAAAGAGGGGGACCTT
AGGGCCTCTTGCCATCGGATGTGCCCAGATGGGATTAGCTAGTAGGTGGG
GTAACGGCTCACCTAGGCGACGATCCCTAGCTGGTCTGAGAGGATGACCA
GCAACACTGGAACTGAGACACGGTCCAGACTCCTACGGGAGGCAGCAGTG
GGGAATATTGCACAATGGGCGCAAGCCTGATGCAGCCATGCGCGTGTATG
AAGAAGGCCTTCGGGTTGTAAAGTACTTTCAGCGGGGAGGAAGGGAGTAA
AGTTAATACCTTTGCTCATTGACGTTACCCGCAGAAGAAGCACCGGCTAA
CTCCGTGCCAGCAGCCGCGGTAATACGGAGGGTGCAAGCGTTAATCGGAA
TTACTGGGCGTAAAGCGCACGCAGGCGGTTTGTTAAGTCAGATGTGAAAT
CCCCGGGCTCAACCTGGGAACTGCATCTGATACTGGCAAGCTTGAGTCTC
GTAGAGGGGGGTAGAATTCCAGGTGTAGCGGTGAAATGCGTAGAGATCTG
GAGGAATACCGGTGGCGAAGGCGGCCCCCTGGACGAAGACTGACGCTCAG
GTGCGAAAGCGTGGGGAGCAAACAGGATTAGATACCCTGGTAGTCCACGC
CGTAAACGATGTCGACTTGGAGGTTGTGCCCTTGAGGCGTGGCTTCCGGA
TAACGCGTTAAGTCGACCGCCTGGGGAGTACGGCCGCAAGGTTAAAACTC
AAATGAATTGACGGGGGCCGCACAAGCGGTGGAGCATGTGGTTTAATTCG
ATGCAACGCGAAGAACCTTACCTGGTCTTGACATCCACGGAAGTTTTCAG
AGATGAGAATGTGCCTTCGGGAACCGTGAGACAGGTGCTGCATGGCTGTC
GTCAGCTCGTGTTGTGAAATGTTGGGTTAAGTCCCGCAACGAGCGCAACC
CTTATCCTTTGTTGCCAGCGGTCCGGCCGGGAACTCAAAGGAGACTGCCA
GTGATAAACTGGAGGAAGGTGGGGATGACGTCAAGTCATCATGGCCCTTA
CGACCAGGGCTACACACGTGCTACAATGGCGCATACAAAGAGAAGCGACC
TCGCGAGAGCAAGCGGACCTCATAAAGTGCGTCGTAGTCCGGATTGGAGT
CTGCAACTCGACTCCATGAAGTCGGAATCGCTAGTAATCGTGGATCAGAA
TGCCACGGTGAATACGTTCCCGGGCCTTGTACACACCGCCCGTCACACCA
TGGGAGTGGGTTGCAAAAGAAGTAGGTAGCTTAACTTCGGGAGGGCG

我为此编写的代码是:

void
output(char *seq, int len){
    for(int i = 0, j = 0; i < len; i++){
        if(seq[i] != '\n'){
                putc(seq[i], stdout);
                j++;
        }
        if(j % 50 == 0)
            putc('\n', stdout);
    }
    putc('\n', stdout);
}

如果输入不包含换行符(上面的第二个示例),这将产生正确的预期结果。但是,如果输入包含换行符(上面的第一个示例),则输出中包含无关的换行符:

AGTTTGATCATGGCTCAGATTGAACGCTGGCGGCAGGCCTAACACATGCA
AGTCGAACGGTAACAGGAAGCAGCTTGCTGCTTTGCTGACGAGTGGCGGA
CGGGTGAGTAATGTCTGGGAAACTGCCTGATGGAGGGGGATAACTACTGG
AAACGGTAGCTAATACCGCATAACGTCGCAAGCACAAAGAGGGGGACCTT
AGGGCCTCTTGCCATCGGATGTGCCCAGATGGGATTAGCTAGTAGGTGGG
GTAACGGCTCACCTAGGCGACGATCCCTAGCTGGTCTGAGAGGATGACCA
GCAACACTGGAACTGAGACACGGTCCAGACTCCTACGGGAGGCAGCAGTG

GGGAATATTGCACAATGGGCGCAAGCCTGATGCAGCCATGCGCGTGTATG
AAGAAGGCCTTCGGGTTGTAAAGTACTTTCAGCGGGGAGGAAGGGAGTAA
AGTTAATACCTTTGCTCATTGACGTTACCCGCAGAAGAAGCACCGGCTAA
CTCCGTGCCAGCAGCCGCGGTAATACGGAGGGTGCAAGCGTTAATCGGAA
TTACTGGGCGTAAAGCGCACGCAGGCGGTTTGTTAAGTCAGATGTGAAAT
CCCCGGGCTCAACCTGGGAACTGCATCTGATACTGGCAAGCTTGAGTCTC
GTAGAGGGGGGTAGAATTCCAGGTGTAGCGGTGAAATGCGTAGAGATCTG
GAGGAATACCGGTGGCGAAGGCGGCCCCCTGGACGAAGACTGACGCTCAG
GTGCGAAAGCGTGGGGAGCAAACAGGATTAGATACCCTGGTAGTCCACGC
CGTAAACGATGTCGACTTGGAGGTTGTGCCCTTGAGGCGTGGCTTCCGGA


TAACGCGTTAAGTCGACCGCCTGGGGAGTACGGCCGCAAGGTTAAAACTC
AAATGAATTGACGGGGGCCGCACAAGCGGTGGAGCATGTGGTTTAATTCG
ATGCAACGCGAAGAACCTTACCTGGTCTTGACATCCACGGAAGTTTTCAG
AGATGAGAATGTGCCTTCGGGAACCGTGAGACAGGTGCTGCATGGCTGTC
GTCAGCTCGTGTTGTGAAATGTTGGGTTAAGTCCCGCAACGAGCGCAACC
CTTATCCTTTGTTGCCAGCGGTCCGGCCGGGAACTCAAAGGAGACTGCCA
GTGATAAACTGGAGGAAGGTGGGGATGACGTCAAGTCATCATGGCCCTTA
CGACCAGGGCTACACACGTGCTACAATGGCGCATACAAAGAGAAGCGACC
TCGCGAGAGCAAGCGGACCTCATAAAGTGCGTCGTAGTCCGGATTGGAGT
CTGCAACTCGACTCCATGAAGTCGGAATCGCTAGTAATCGTGGATCAGAA
TGCCACGGTGAATACGTTCCCGGGCCTTGTACACACCGCCCGTCACACCA
TGGGAGTGGGTTGCAAAAGAAGTAGGTAGCTTAACTTCGGGAGGGCG

我试过使用模数周围的数字,但无济于事。我不确定为什么这会失败。我怎样才能使这段代码按预期运行?

只需将if条件检查new-break-length移到里面即可。

您还可以使用本地 look-up table.

限制检查允许的核苷酸

注意到输入中有三 (3) 个 N。 Wiki Nucleotide - Abbreviation Codes,说 any base (not a gap),但预期输出和您的错误输出没有它们。

#define LINE_BREAK_LEN  50
void
output (const char *seq, const int len) {
    char nlt [256] = {0};
    nlt ['A'] = nlt['G'] = nlt['C'] = nlt['T'] = nlt['U'] = 1;
    //nlt ['a'] = nlt['g'] = nlt['c'] = nlt['t'] = nlt['u'] = 1; // in case you want to allow lower-case too

    for (int i = 0, j = 0; i < len; i++) {
        if (nlt [(unsigned char) seq[i]]) {
            putc (seq[i], stdout);
            j++;
            if (0 == (j % LINE_BREAK_LEN))
                putc ('\n', stdout);
        }
    }
    putc ('\n', stdout);
}