Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-23T22:02:00.460Z
Answers.Text: Super helpful. Thank you!
Answers.UserDisplayName: Mark Pauley
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-23T22:07:33.637Z
Answers.Text: 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.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-21T10:37:16.067Z
Answers.LastActivityDate: 2022-06-21T10:37:16.067Z
Answers.UserDisplayName: terdon
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-20T14:53:17.277Z
Answers.Text: 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.
Answers.UserDisplayName: Mark Pauley
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-20T17:09:42.173Z
Answers.Text: 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.
Answers.UserDisplayName: helrick
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-21T10:26:07.387Z
Answers.Text: 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.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-21T10:37:47.977Z
Answers.Text: Relevant: [Why is using a shell loop to process text considered bad practice?](https://unix.stackexchange.com/q/169716)
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-06-15T14:51:32.567Z
Answers.LastActivityDate: 2022-06-15T15:54:03.723Z
Answers.LastEditDate: 2022-06-15T15:54:03.723Z
Answers.UserDisplayName: helrick
Body: <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>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-06-14T18:39:50.007Z
Comments.Text: 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?
Comments.UserDisplayName: Maximilian Press
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-06-14T19:27:31.837Z
Comments.Text: 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.
Comments.UserDisplayName: Community
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2022-06-21T10:27:26.940Z
Comments.Text: 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.
Comments.UserDisplayName: terdon
Tags: <fasta><phylogenetics><grep>
Title: Elegant Way to Extract Gene Symbols from FASTA Headers
ThreadText: # 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, @username_0. 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)  
  
  ---
  
  