<p>We can't be sure without seeing your file, but if what you really want is the text between the last parentheses on lines that start with <code>&gt;</code>, then you can do this with GNU <code>grep</code> (the default on Linux) with:</p>
<pre><code>grep -oP '^&gt;.*\(\K[^)]+' file.fa
</code></pre>
<p>The <code>-o</code> means &quot;print only the matching portion of the line&quot; and the <code>-P</code> activates Perl Compatible Regular Expressions (PCREs). The regex looks for a <code>&gt;</code> at the beginning of the line (<code>^&gt;</code>), then as many characters as possible until the last parenthesis (<code>.*\(</code>), and then forgets everything matched up to this point with the <code>\K</code>. This means that the <code>-o</code> will only see things <em>after</em> the <code>\K</code>, a PCRE feature. So finally, we look for the longest stretch of one or more non<code>-)</code> characters.</p>
<p>If you don't have GNU <code>grep</code>, you can do the same basic thing with <code>perl</code> or <code>sed</code>:</p>
<pre><code>sed -n 's/^&gt;.*(\([^)]*\).*/\1/p' file.fa
perl -lne '/^&gt;.*\(([^)]+)/ &amp;&amp; print $1' file.fa
</code></pre>

CC BY-SA 4.0
2022-06-23T22:02:00.460Z
Super helpful. Thank you!
Mark Pauley
CC BY-SA 4.0
2022-06-23T22:07:33.637Z
You're very welcome, @MarkPauley. If one of the answers here solved your issue, please take a moment and [accept it](//bioinformatics.stackexchange.com/help/someone-answers) by clicking on the checkmark on the left. That is the best way to express your thanks on the Stack Exchange sites.
terdon
CC BY-SA 4.0
2022-06-21T10:37:16.067Z
2022-06-21T10:37:16.067Z
terdon
<p>There are probably better ways of doing this with Python or another tool, but here's a quick method that works in bash (tested on Linux) assuming that the Gene Symbols are contained in parentheses, i.e. &quot;(Gene Symbol)&quot;:</p>
<pre><code>pat='\(([^)]+)\)'
while read line; do 
    if [[ &quot;<span class="math-container">$line" =~ $</span>pat ]]; then 
        echo ${BASH_REMATCH[1]}; 
    fi; 
done &lt; human.1.rna.fna
</code></pre>

CC BY-SA 4.0
2022-06-20T14:53:17.277Z
Thanks. Unfortunately, there can be more than one parenthesized expression in the header, so this pattern is too permissive. In every record I've looked at, the gene symbol is in the last parenthesized expression, but I don't know if that is guaranteed to be true.
Mark Pauley
CC BY-SA 4.0
2022-06-20T17:09:42.173Z
Could you maybe use another file provided by the RefSeq ftp such as [this one](https://ftp.ncbi.nlm.nih.gov/refseq/H_sapiens/RefSeqGene/LRG_RefSeqGene)? It may have more genes than in your FASTA file, I'm assuming not fewer, but you could always do a quick check using the regex output as a comparison by sorting both files, and performing a `diff` command in Linux.
helrick
CC BY-SA 4.0
2022-06-21T10:26:07.387Z
You really, really don't want to do this in the shell. It is going to be orders of magnitude slower than anything else and is very hard to get right. For example, your entire loop can be done faster and simpler with `grep '\([^)]*\) human.1.rna.fna`. The loop only makes it slower and more fragile.
terdon
CC BY-SA 4.0
2022-06-21T10:37:47.977Z
Relevant: [Why is using a shell loop to process text considered bad practice?](https://unix.stackexchange.com/q/169716)
terdon
CC BY-SA 4.0
2022-06-15T14:51:32.567Z
2022-06-15T15:54:03.723Z
2022-06-15T15:54:03.723Z
helrick
<p>I've downloaded the RefSeq transcript sequences (FASTA format) for the GRC38 patch 14 build of the human genome and would now like to extract the gene symbols (only) in order from the headers. I'm confident I can do this using <code>grep</code> and regular expressions--the trick will be coming up with an appropriate pattern. (The gene symbol <em>appears</em> to be surrounded by the last pair of parentheses in a header, but I'm not sure this is absolutely true.) However, I'm wondering if there is a more elegant way to do this--e.g., via the NCBI EDirect utilities or <code>SeqKit</code>--that I'm overlooking. (I have a list of the accession.version numbers.) Any thoughts on this would be greatly appreciated.</p>

CC BY-SA 4.0
2022-06-14T18:39:50.007Z
It would be helpful to see a sample of the file or a direct link to the file in question. Is there a reason that you want to do this from the FASTA header (which is probably not so strictly curated) rather than from a more traditional annotation file format such as GFF3?
Maximilian Press
CC BY-SA 4.0
2022-06-14T19:27:31.837Z
Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.
Community
CC BY-SA 4.0
2022-06-21T10:27:26.940Z
We can't help you parse data if you don't show us what you need to parse. Please [edit] your question and show us a few lines (preferably just fasta header lines) of your file and the output you would want from that example.
terdon
<fasta><phylogenetics><grep>
Elegant Way to Extract Gene Symbols from FASTA Headers
# Elegant Way to Extract Gene Symbols from FASTA Headers

(Asked by: username_0 on 2022-06-14)

I've downloaded the RefSeq transcript sequences (FASTA format) for the GRC38 patch 14 build of the human genome and would now like to extract the gene symbols (only) in order from the headers. I'm confident I can do this using `grep` and regular expressions--the trick will be coming up with an appropriate pattern. (The gene symbol *appears* to be surrounded by the last pair of parentheses in a header, but I'm not sure this is absolutely true.) However, I'm wondering if there is a more elegant way to do this--e.g., via the NCBI EDirect utilities or `SeqKit`--that I'm overlooking. (I have a list of the accession.version numbers.) Any thoughts on this would be greatly appreciated.

**Tags:** fasta, phylogenetics, grep
> **Comments:**
> **username_1**: It would be helpful to see a sample of the file or a direct link to the file in question. Is there a reason that you want to do this from the FASTA header (which is probably not so strictly curated) rather than from a more traditional annotation file format such as GFF3?  
> **username_2**: Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking.  
> **username_3**: We can't help you parse data if you don't show us what you need to parse. Please [edit] your question and show us a few lines (preferably just fasta header lines) of your file and the output you would want from that example.  

---

## 2 answers

### Answer by username_3 on 2022-06-21. Score: 1

We can't be sure without seeing your file, but if what you really want is the text between the last parentheses on lines that start with >, then you can do this with GNU grep (the default on Linux) with:
grep -oP '^>.*\(\K[^)]+' file.fa

The -o means "print only the matching portion of the line" and the -P activates Perl Compatible Regular Expressions (PCREs). The regex looks for a > at the beginning of the line (^>), then as many characters as possible until the last parenthesis (.*\(), and then forgets everything matched up to this point with the \K. This means that the -o will only see things after the \K, a PCRE feature. So finally, we look for the longest stretch of one or more non-) characters.
If you don't have GNU grep, you can do the same basic thing with perl or sed:
sed -n 's/^>.*(\([^)]*\).*/\1/p' file.fa
perl -lne '/^>.*\(([^)]+)/ && print $1' file.fa

> **Comments:**
> **username_0**: Super helpful. Thank you!  
> **username_3**: You're very welcome, @MarkPauley. If one of the answers here solved your issue, please take a moment and [accept it](//bioinformatics.stackexchange.com/help/someone-answers) by clicking on the checkmark on the left. That is the best way to express your thanks on the Stack Exchange sites.  

---

### Answer by username_4 on 2022-06-15. Score: 0

There are probably better ways of doing this with Python or another tool, but here's a quick method that works in bash (tested on Linux) assuming that the Gene Symbols are contained in parentheses, i.e. "(Gene Symbol)":
pat='\(([^)]+)\)'
while read line; do 
    if [[ "$line" =~ $pat ]]; then 
        echo ${BASH_REMATCH[1]}; 
    fi; 
done < human.1.rna.fna

> **Comments:**
> **username_0**: Thanks. Unfortunately, there can be more than one parenthesized expression in the header, so this pattern is too permissive. In every record I've looked at, the gene symbol is in the last parenthesized expression, but I don't know if that is guaranteed to be true.  
> **username_4**: Could you maybe use another file provided by the RefSeq ftp such as [this one](https://ftp.ncbi.nlm.nih.gov/refseq/H_sapiens/RefSeqGene/LRG_RefSeqGene)? It may have more genes than in your FASTA file, I'm assuming not fewer, but you could always do a quick check using the regex output as a comparison by sorting both files, and performing a `diff` command in Linux.  
> **username_3**: You really, really don't want to do this in the shell. It is going to be orders of magnitude slower than anything else and is very hard to get right. For example, your entire loop can be done faster and simpler with `grep '\([^)]*\) human.1.rna.fna`. The loop only makes it slower and more fragile.  
> **username_3**: Relevant: [Why is using a shell loop to process text considered bad practice?](https://unix.stackexchange.com/q/169716)  

---

