<p>If you have GNU <code>grep</code> (default on Linux), you can do this with a single <code>grep</code> command using Perl Compatible Regular Expressions (PCREs):</p>

<pre><code>$ grep -oP 'GeneID:\d+|/(gene|product|protein_id)="\K[^"]+' file | sort -u
GeneID:100933602
uroporphyrinogen-III synthase isoform X1
UROS
XP_003755055.2
</code></pre>

<p>The <code>-o</code> flag tells <code>grep</code> to only print the matching portion of the line and the <code>-P</code> enables PCREs which let us use <code>d+</code> for "one or more digits" and <code>\K</code> which means "discard whatever was matched before the <code>\K</code>".</p>

<p>Note that I'm not using <code>cat</code> here. The command from your question is what is known as a <a href="http://porkmail.org/era/unix/award.html" rel="nofollow noreferrer">UUoC</a> (useless use of cat) and is a surefire way of annoying any *nix geeks around ;).  </p>

<hr>

<p>If you don't have GNU <code>grep</code>, you can do something like this:</p>

<pre><code>$ awk -F= '/GeneID:|(gene|product|protein_id)=/{print $2}' file | 
    tr -d '"' | sort -u
GeneID:100933602
uroporphyrinogen-III synthase isoform X1
UROS
XP_003755055.2
</code></pre>

CC BY-SA 4.0
2018-09-17T16:13:45.317Z
Thank you so much! Also, what to do if the "uroporphyrinogen-III synthase isoform X1" string was on more than one line?
Aron van Beelen
CC BY-SA 4.0
2018-09-17T16:18:57.807Z
@AronvanBeelen ah, that is a very, very different situation. Is that even a valid genbank file? How would it look like? You would also need to remove the spaces on the second line, right? That is approaching the level of complexity where it is better to write a proper parser instead of hacking something together on the command line. You might want to ask a new question, showing an example that accurately represents your real data.
terdon
CC BY-SA 4.0
2018-09-17T16:37:49.237Z
I've asked a new question, I hope you can help me! :)
Aron van Beelen
CC BY-SA 4.0
2018-09-17T08:17:16.950Z
2018-09-17T08:17:16.950Z
terdon
<p>If you change the delimiter to something besides a space in the <code>tr</code> command (<code>tr "\"" "\t"</code>) then you can use that same delimiter in the <code>awk</code> command (<code>-F "\t"</code>).  In my example below I used a tab, also I filtered the taxon prior to the <code>tr</code> so that you don't have to worry about that staying in sync if you change the delimiter.</p>

<pre><code> egrep -v "/db_xref=\"taxon"| tr "\"" "\t" | egrep "/gene=|/db_xref=|/product=|/protein_id=" | sort | uniq | awk -F "\t" '{print($2)}END{print("")}';
</code></pre>

<p>results:</p>

<pre><code>GeneID:100933602
UROS
uroporphyrinogen-III synthase isoform X1
XP_003755055.2
</code></pre>

CC BY-SA 4.0
2018-09-16T16:29:28.810Z
2018-09-16T16:29:28.810Z
Bioathlete
<p>The solutions here are more robust than mine since I rely on the structure of the file, but if you want a solution that is really easy to understand:</p>

<pre><code>$grep -A 5 "CDS" file | grep -v "CDS" | grep -v "codon_start" | cut -f 2 -d \"
UROS
uroporphyrinogen-III synthase isoform X1
XP_003755055.2
GeneID:100933602
</code></pre>

<p>I take CDS line and 5 lines bellow, then I kick out CDS and codon_start (lines we are not interested in) and then I just bring what is between quote using cut. I also report the values in the order as they appear in the original file.</p>

CC BY-SA 4.0
2018-09-18T20:52:55.287Z
2018-09-18T20:52:55.287Z
Kamil S Jaron
<p>I need the name of the protein in /product="protein_name" using bash commands. Beware, there is a lot of whitespace between lines.</p>

<pre><code>FEATURES             Location/Qualifiers
     source          1..1266
                     /organism="Sarcophilus harrisii"
                     /mol_type="mRNA"
                     /isolate="Salem"
                     /db_xref="taxon:9305"
                     /chromosome="1"
                     /map="unlocalized"
                     /sex="female"
                     /country="Australia: Taronga Zoo, Sydney"
     gene            1..1266
                     /gene="UROS"
                     /note="Derived by automated computational analysis using
                     gene prediction method: Gnomon. Supporting evidence
                     includes similarity to: 10 Proteins, and 100% coverage of
                     the annotated genomic feature by RNAseq alignments,
                     including 5 samples with support for all annotated
                     introns"
                     /db_xref="GeneID:100933602"
     CDS             60..908
                     /gene="UROS"
                     /codon_start=1
                     /product="uroporphyrinogen-III synthase isoform X1"
                     /protein_id="XP_003755055.2"
                     /db_xref="GeneID:100933602"
                     /translation="MRIPTSFSRGAWWKMKVLLLKDAKDDDSGLDPYLQELGSCGFEA
                     TLIPVLAFEFLSLPSFSEKLSHPEAYGGLVFTSPRAVEALQLSLERAGQLEVWKKSLK
                     EKWRLKPAYVVGQATASLVKKVGLAAEGEKCGNGEKLAEYICSRETPATLPLLFPCGT
                     LKGEVLPKTLKQKGILLESLTVYQKVQHPRMQDSLKSYFSTQGVPAGVTFFSPSGLTY
                     SLPHIQELSGASFDRIKFAAIGPTTARALASAGIPVSCTAEKPCPQDLAAGLQKALQP
                     SGPSSS"
</code></pre>

<p>Right now I have this:</p>

<pre><code>while read p;
do cat "${p}.gb" | tr "\"" " "| egrep -v "/db_xref= taxon"| egrep "/gene=|/db_xref=|/product=|/protein_id=" | sort | uniq | awk '{print($2)}END{print("")}'
done &lt;XM_codes.txt
</code></pre>

<p>Which results in this:</p>

<pre><code>GeneID:100933602
UROS
uroporphyrinogen-111
XP_003755055.2
</code></pre>

<p>My output should be:</p>

<pre><code>GeneID:100933602
UROS
uroporphyrinogen-III synthase isoform X1
XP_003755055.2
</code></pre>

<proteins><linux><genbank><bash>
How to get the product of a CDS
# How to get the product of a CDS

(Asked by: username_0 on 2018-09-16)

I need the name of the protein in /product="protein_name" using bash commands. Beware, there is a lot of whitespace between lines.
FEATURES             Location/Qualifiers
     source          1..1266
                     /organism="Sarcophilus harrisii"
                     /mol_type="mRNA"
                     /isolate="Salem"
                     /db_xref="taxon:9305"
                     /chromosome="1"
                     /map="unlocalized"
                     /sex="female"
                     /country="Australia: Taronga Zoo, Sydney"
     gene            1..1266
                     /gene="UROS"
                     /note="Derived by automated computational analysis using
                     gene prediction method: Gnomon. Supporting evidence
                     includes similarity to: 10 Proteins, and 100% coverage of
                     the annotated genomic feature by RNAseq alignments,
                     including 5 samples with support for all annotated
                     introns"
                     /db_xref="GeneID:100933602"
     CDS             60..908
                     /gene="UROS"
                     /codon_start=1
                     /product="uroporphyrinogen-III synthase isoform X1"
                     /protein_id="XP_003755055.2"
                     /db_xref="GeneID:100933602"
                     /translation="MRIPTSFSRGAWWKMKVLLLKDAKDDDSGLDPYLQELGSCGFEA
                     TLIPVLAFEFLSLPSFSEKLSHPEAYGGLVFTSPRAVEALQLSLERAGQLEVWKKSLK
                     EKWRLKPAYVVGQATASLVKKVGLAAEGEKCGNGEKLAEYICSRETPATLPLLFPCGT
                     LKGEVLPKTLKQKGILLESLTVYQKVQHPRMQDSLKSYFSTQGVPAGVTFFSPSGLTY
                     SLPHIQELSGASFDRIKFAAIGPTTARALASAGIPVSCTAEKPCPQDLAAGLQKALQP
                     SGPSSS"

Right now I have this:
while read p;
do cat "${p}.gb" | tr "\"" " "| egrep -v "/db_xref= taxon"| egrep "/gene=|/db_xref=|/product=|/protein_id=" | sort | uniq | awk '{print($2)}END{print("")}'
done 
Which results in this:
GeneID:100933602
UROS
uroporphyrinogen-111
XP_003755055.2

My output should be:
GeneID:100933602
UROS
uroporphyrinogen-III synthase isoform X1
XP_003755055.2

**Tags:** proteins, linux, genbank, bash

---

## 3 answers

### Answer by username_1 on 2018-09-17. Score: 0 | Accepted answer

If you have GNU grep (default on Linux), you can do this with a single grep command using Perl Compatible Regular Expressions (PCREs):
$ grep -oP 'GeneID:\d+|/(gene|product|protein_id)="\K[^"]+' file | sort -u
GeneID:100933602
uroporphyrinogen-III synthase isoform X1
UROS
XP_003755055.2

The -o flag tells grep to only print the matching portion of the line and the -P enables PCREs which let us use d+ for "one or more digits" and \K which means "discard whatever was matched before the \K".
Note that I'm not using cat here. The command from your question is what is known as a UUoC (useless use of cat) and is a surefire way of annoying any *nix geeks around ;).  

If you don't have GNU grep, you can do something like this:
$ awk -F= '/GeneID:|(gene|product|protein_id)=/{print $2}' file | 
    tr -d '"' | sort -u
GeneID:100933602
uroporphyrinogen-III synthase isoform X1
UROS
XP_003755055.2

> **Comments:**
> **username_0**: Thank you so much! Also, what to do if the "uroporphyrinogen-III synthase isoform X1" string was on more than one line?  
> **username_1**: @AronvanBeelen ah, that is a very, very different situation. Is that even a valid genbank file? How would it look like? You would also need to remove the spaces on the second line, right? That is approaching the level of complexity where it is better to write a proper parser instead of hacking something together on the command line. You might want to ask a new question, showing an example that accurately represents your real data.  
> **username_0**: I've asked a new question, I hope you can help me! :)  

---

### Answer by username_2 on 2018-09-16. Score: 3

If you change the delimiter to something besides a space in the tr command (tr "\"" "\t") then you can use that same delimiter in the awk command (-F "\t").  In my example below I used a tab, also I filtered the taxon prior to the tr so that you don't have to worry about that staying in sync if you change the delimiter.
 egrep -v "/db_xref=\"taxon"| tr "\"" "\t" | egrep "/gene=|/db_xref=|/product=|/protein_id=" | sort | uniq | awk -F "\t" '{print($2)}END{print("")}';

results:
GeneID:100933602
UROS
uroporphyrinogen-III synthase isoform X1
XP_003755055.2


---

### Answer by username_3 on 2018-09-18. Score: 0

The solutions here are more robust than mine since I rely on the structure of the file, but if you want a solution that is really easy to understand:
$grep -A 5 "CDS" file | grep -v "CDS" | grep -v "codon_start" | cut -f 2 -d \"
UROS
uroporphyrinogen-III synthase isoform X1
XP_003755055.2
GeneID:100933602

I take CDS line and 5 lines bellow, then I kick out CDS and codon_start (lines we are not interested in) and then I just bring what is between quote using cut. I also report the values in the order as they appear in the original file.


---

