2

So I have files like this but for hundreds of different genes per file.

>lcl|accession_cds_proteinaccession [gene=dnaA] [protein=description] [protein_id=accession] [location=location]
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACT
CAACTTTCCTAAAAGATACTGAGCTTTACACGATTAAAGATGGTGAAGCTATCGTATTATCGAGTATTCC
TTTTAATGCAAATTGGTTAAATCAACAATATGCTGAAATTATCCAAGCAATCTTATTTGATGTTGTAGGC

There are lots of duplicate gene names such that the gene=dnaA might appear a few times throughout the file. I need it to be so that if the gene name is repeated is adds a 2 to the end of the name. So for the second duplicate in a file it changes [gene=dnaA] to [gene=dnaA2] and for the third repeat [gene=dnaA3]. If it matters, I know there aren't any gene names duplicated more than 6 times. A sample output would look like

lcl|accession_cds_proteinaccession [gene=dnaA] [protein=description] [protein_id=accession] [location=location]
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACT
CAACTTTCCTAAAAGATACTGAGCTTTACACGATTAAAGATGGTGAAGCTATCGTATTATCGAGTATTCC

lcl|accession_cds_proteinaccession [gene=dnaA2] [protein=description] [protein_id=accession] [location=location]
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACT
CAACTTTCCTAAAAGATACTGAGCTTTACACGATTAAAGATGGTGAAGCTATCGTATTATCGAGTATTCC

lcl|accession_cds_proteinaccession [gene=dnaA3] [protein=description] [protein_id=accession] [location=location]
ATGTCGGAAAAAGAAATTTGGGAAAAAGTGCTTGAAATTGCTCAAGAAAAATTATCAGCTGTAAGTTACT
CAACTTTCCTAAAAGATACTGAGCTTTACACGATTAAAGATGGTGAAGCTATCGTATTATCGAGTATTCC
TTTTAATGCAAATTGGTTAAATCAACAATATGCTGAAATTATCCAAGCAATCTTATTTGATGTTGTAGGC

I have seen answers on here that use awk to add characters to the end of lines containing duplicate words (I want to find duplicates in a file and add a character to the end of the line on the 1st match). But I need to add characters to the end of the words that are duplicated with the characters denoting the number of times its been duplicated.

Even if you can just point me in the right direction that would be a huge help!

Thank you

3

Perl one-liner:

perl -pe's/\[gene=([^\]]*)\K\]/$h{$1}++?"$h{$1}]":"]"/e' yourfile

Explained:

  • -p: execute the code for each line of the file (stored in $_) and print $_ at the end.
  • -e: code.
  • s/regex/replacement/e: Match regex and replace it with replacement on $_.

The regex:

/\[gene=    # match [gene= 
 ([^\]]*)   # match anything but "]" and put it a matching group
 \K         # don't “take” anything until here
 \]         # match a literal ]
/x

The replacement:

  • condition ? yes : no: classic ternary operator (read like an if with return)
  • $h{$1}++: store the contents of the first matching group in a hash (dictonary, mapping…) and raise the value by one. Returns 0, which is false on the first encounter.

  • "$h{$1}]": read the value for $1 and interpolate it within a string.

If you want in-file-replacement, add an -i after the perl. You can supply an optional file ending for a backup file to the -i flag (for example perl -i'.bak' -pe'…' yourfile changes yourfile and creates a yourfile.bak from before the replacement.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.