Answers.Body: <p>It seems like you want to do four things:</p>
  
  <ol>
  <li>Remove all text up to and including the first <code>|</code>.</li>
  <li>Now that that has been removed, take the string between what is now (after step 1) the first <code>|</code> and what is now the second <code>|</code>, and append it to the end of the header with a <code>_</code>. </li>
  <li>Replace all <code>__</code> with <code>:</code> and all <code>;</code> with <code>,</code>.</li>
  <li>Change the (fixed?) string <code>reps|k</code> with <code>tax=d</code>.</li>
  </ol>
  
  <p>If so, and assuming that you only have one occurrence of <code>reps|</code> in each header, you can do:</p>
  
  <pre><code>$ sed 's/&gt;[^|]*|/&gt;/; 
         s/reps|k/tax=d/; 
         s/__/:/g; 
         s/;/,/g; 
         s/|\([^|]*\)\(|.*\)/|\1\2_\1;/; ' file.fa 
  &gt;JF514531|SH174817.07FU;tax=d:Fungi,p:Basidiomycota,c:Agaricomycetes,o:Agaricales,f:Agaricaceae,g:Agaricus,s:Agaricus_chiangmaiensis_SH174817.07FU;
  </code></pre>
  
  <p>This will:</p>
  
  <ul>
  <li><code>s/&gt;[^|]*|/&gt;/</code> : replace the longest stretch of non<code>-|</code> characters after a <code>&gt;</code> and until the first <code>|</code> with <code>&gt;</code> alone.</li>
  <li><code>s/reps|k/tax=d/;</code> : replace the first occurrence of the string <code>reps|k</code> with <code>tax=</code>.</li>
  <li><code>s/__/:/g; s/;/,/g</code> : replace <em>all</em> (that's what the <code>/g</code> means) occurrences of <code>__</code> with <code>:</code> and of <code>;</code> with <code>,</code>.</li>
  <li><p><code>s/|\([^|]*\)\(|.*\)/|\1\2_\1;/</code> : the <code>\(foo\)</code> construct is called a <a href="https://www.regular-expressions.info/brackets.html" rel="nofollow noreferrer">capturing group</a> and will <em>capture</em> <code>foo</code> and save it as <code>\1</code>, which can be used on the right hand side of the replacement operator. The next captured group will be <code>\2</code> then <code>\3</code> etc. Here, with <code>|\([^|]*\)</code> we are capturing the longest string of non<code>|</code> found after the 1st <code>|</code> (this happens after the first operation, so the 1st <code>|</code> is the one that was 3rd in the original) and then everything after the next <code>|</code> (<code>|.*</code>) until the end of the line. We then replace everything matched with a <code>|</code>, then whatever was matched by the first capture group (<code>\1</code>), then the second (<code>\2</code>), then we add a <code>_</code> and repeat the <code>\1</code>. 
  Finally, if you want to make the changes to the original input file, use <code>-i</code>:</p>
  
  <pre><code>sed -i.bak 's/&gt;[^|]*|/&gt;/; s/reps|k/tax=d/; s/__/:/g; s/;/,/g; s/|\([^|]*\)\(|.*\)/|\1\2_\1;/; ' file.fa
  </code></pre>
  
  <p>That will save the original file as <code>file.fa.bak</code>. use <code>-i</code> alone without any argument if you don't need the backup. </p></li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-22T18:27:12.470Z
Answers.Text: This works really well, except for two things:  the command changes reps to tax for every other header, and there is still a | in front of tax instead of ;.
Answers.UserDisplayName: Graham
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-19T13:20:05.290Z
Answers.LastActivityDate: 2019-01-22T17:37:23.440Z
Answers.LastEditDate: 2019-01-22T17:37:23.440Z
Answers.UserDisplayName: terdon
Answers.Body: <p>If <code>awk</code> is good as well:</p>
  
  <pre><code><span class="math-container">$ awk -v FS="|" -v OFS="|" '/&gt;/{
      gsub(";",",", $5); 
      gsub("__",":",$5); 
      print "&gt;"$2,$3";tax="$5"_"$</span>3";";
      next;
  }1' file.fa
  &gt;JF514531|SH174817.07FU;tax=k:Fungi,p:Basidiomycota,c:Agaricomycetes,o:Agaricales,f:Agaricaceae,g:Agaricus,s:Agaricus_chiangmaiensis_SH174817.07FU;
  </code></pre>
  
  <p>This relies on the order of the parts separated by <code>|</code>.</p>
  
  <p>I don't understand why <code>k__Fungi</code> becomes <code>d:Fungi</code>, so I ignored it for now. </p>
  
  <p>Some explanation for what <code>awk</code>is doing.</p>
  
  <ul>
  <li><code>|</code> is defined as a field (column) separator for the input and output</li>
  <li>If the line contains a <code>&gt;</code> the code between <code>{</code> and <code>}</code> is executed.</li>
  <li>the first <code>gsub</code> replaces <code>;</code> with <code>,</code> in the 5th field</li>
  <li>the second <code>gsub</code> replaces <code>__</code> with <code>:</code> in the 5th field</li>
  <li>then we print the new header line. The <code><span class="math-container">$2</code>, <code>$</span>3</code> and <code><span class="math-container">$5</code> get replaced by the values of the second, third and 5th field of the input. <code>,</code> get replaced by the defined output field separator</li>
  <li>with <code>next</code> we tell <code>awk</code> to go to the next input line and repeat the code</li>
  <li>The <code>1</code> is in equivalent to <code>print $</span>0</code> for printing the whole input line. In our code this is only executed if the line is no header line. </li>
  </ul>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-22T11:48:04.393Z
Answers.Text: I don't know awk that well. However, I find this is a really nice example and it makes me want to learn more awk!
Answers.UserDisplayName: winni2k
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-22T17:40:38.123Z
Answers.Text: Note that this won't print the sequences, only the header.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-22T18:32:20.567Z
Answers.Text: I just noticed this - how would you change this?
Answers.UserDisplayName: Graham
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-22T18:55:14.263Z
Answers.Text: I edited my answer.
Answers.UserDisplayName: finswimmer
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2019-01-19T08:09:15.683Z
Answers.LastActivityDate: 2019-01-22T19:20:40.970Z
Answers.LastEditDate: 2019-01-22T19:20:40.970Z
Answers.UserDisplayName: finswimmer
Body: <p>I appologize for asking this, but I really am really bad with regex...</p>
  
  <p>Can someone help me transform the headers of my fasta files from this:</p>
  
  <pre><code>&gt;Agaricus_chiangmaiensis|JF514531|SH174817.07FU|reps|k__Fungi;p__Basidiomycota;c__Agaricomycetes;o__Agaricales;f__Agaricaceae;g__Agaricus;s__Agaricus_chiangmaiensis
  </code></pre>
  
  <p>to this:</p>
  
  <pre><code>&gt;JF514531|SH174817.07FU;tax=d:Fungi,p:Basidiomycota,c:Agaricomycetes,o:Agaricales,f:Agaricaceae,g:Agaricus,s:Agaricus_chiangmaiensis_SH174817.07FU;
  </code></pre>
  
  <p>seems like I could use the command </p>
  
  <pre><code>sed 's/__/:/g;s/;/,/g;s/.*|/|/g' 
  </code></pre>
  
  <p>to substitute <code>:</code> for <code>__</code>, and <code>,</code> for <code>;</code>.  I'm not entirely sure how to proceed from there though...</p>
  
  <p>Thank you</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-01-19T13:11:52.027Z
Comments.Text: Could you [edit] your question and explain the transformation you need please? You don't only want to replace `__` with `:` and `;` with `,`. You also seem to be removing some text. Do you always want to remove whatever is before the first `|`? And what happened to the `reps`? And why is `k__Fungi` becoming `tax=d:Fungi` instead of `k:Fungi`? We need to know exactly what you are trying to do in order to give an answer that works for you.
Comments.UserDisplayName: terdon
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2019-01-22T17:35:25.583Z
Comments.Text: Looks like you figured it out without more clarification - I'll try to be more concise when asking in the future -
Comments.UserDisplayName: Graham
Tags: <fasta><text-processing>
Title: How do I re-name the headers of my Fasta file?
ThreadText: # How do I re-name the headers of my Fasta file?
  
  (Asked by: username_0 on 2019-01-19)
  
  I appologize for asking this, but I really am really bad with regex...
  
  Can someone help me transform the headers of my fasta files from this:
  
  ```
  >Agaricus_chiangmaiensis|JF514531|SH174817.07FU|reps|k__Fungi;p__Basidiomycota;c__Agaricomycetes;o__Agaricales;f__Agaricaceae;g__Agaricus;s__Agaricus_chiangmaiensis
  
  ```
  
  to this:
  
  ```
  >JF514531|SH174817.07FU;tax=d:Fungi,p:Basidiomycota,c:Agaricomycetes,o:Agaricales,f:Agaricaceae,g:Agaricus,s:Agaricus_chiangmaiensis_SH174817.07FU;
  
  ```
  
  seems like I could use the command
  
  ```
  sed 's/__/:/g;s/;/,/g;s/.*|/|/g' 
  
  ```
  
  to substitute `:` for `__`, and `,` for `;`. I'm not entirely sure how to proceed from there though...
  
  Thank you
  
  **Tags:** fasta, text-processing
  
  > **Comments:**
  > **username_1**: Could you [edit] your question and explain the transformation you need please? You don't only want to replace `__` with `:` and `;` with `,`. You also seem to be removing some text. Do you always want to remove whatever is before the first `|`? And what happened to the `reps`? And why is `k__Fungi` becoming `tax=d:Fungi` instead of `k:Fungi`? We need to know exactly what you are trying to do in order to give an answer that works for you.  
  > **username_0**: Looks like you figured it out without more clarification - I'll try to be more concise when asking in the future -  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_2 on 2019-01-19. Score: 5 | Accepted answer
  
  If `awk` is good as well:
  
  ```
  $ awk -v FS="|" -v OFS="|" '/>/{
      gsub(";",",", $5); 
      gsub("__",":",$5); 
      print ">"$2,$3";tax="$5"_"$3";";
      next;
  }1' file.fa
  >JF514531|SH174817.07FU;tax=k:Fungi,p:Basidiomycota,c:Agaricomycetes,o:Agaricales,f:Agaricaceae,g:Agaricus,s:Agaricus_chiangmaiensis_SH174817.07FU;
  
  ```
  
  This relies on the order of the parts separated by `|`.
  
  I don't understand why `k__Fungi` becomes `d:Fungi`, so I ignored it for now.
  
  Some explanation for what `awk`is doing.
  
  * `|` is defined as a field (column) separator for the input and output
  * If the line contains a `>` the code between `{` and `}` is executed.
  * the first `gsub` replaces `;` with `,` in the 5th field
  * the second `gsub` replaces `__` with `:` in the 5th field
  * then we print the new header line. The `$2`, `$3` and `$5` get replaced by the values of the second, third and 5th field of the input. `,` get replaced by the defined output field separator
  * with `next` we tell `awk` to go to the next input line and repeat the code
  * The `1` is in equivalent to `print $0` for printing the whole input line. In our code this is only executed if the line is no header line.
  
  > **Comments:**
  > **username_3**: I don't know awk that well. However, I find this is a really nice example and it makes me want to learn more awk!  
  > **username_1**: Note that this won't print the sequences, only the header.  
  > **username_0**: I just noticed this - how would you change this?  
  > **username_2**: I edited my answer.  
  
  ---
  
  ### Answer by username_1 on 2019-01-19. Score: 3
  
  It seems like you want to do four things:
  
  1. Remove all text up to and including the first `|`.
  2. Now that that has been removed, take the string between what is now (after step 1) the first `|` and what is now the second `|`, and append it to the end of the header with a `_`.
  3. Replace all `__` with `:` and all `;` with `,`.
  4. Change the (fixed?) string `reps|k` with `tax=d`.
  
  If so, and assuming that you only have one occurrence of `reps|` in each header, you can do:
  
  ```
  $ sed 's/>[^|]*|/>/; 
         s/reps|k/tax=d/; 
         s/__/:/g; 
         s/;/,/g; 
         s/|\([^|]*\)\(|.*\)/|\1\2_\1;/; ' file.fa 
  >JF514531|SH174817.07FU;tax=d:Fungi,p:Basidiomycota,c:Agaricomycetes,o:Agaricales,f:Agaricaceae,g:Agaricus,s:Agaricus_chiangmaiensis_SH174817.07FU;
  
  ```
  
  This will:
  
  * `s/>[^|]*|/>/` : replace the longest stretch of non`-|` characters after a `>` and until the first `|` with `>` alone.
  * `s/reps|k/tax=d/;` : replace the first occurrence of the string `reps|k` with `tax=`.
  * `s/__/:/g; s/;/,/g` : replace *all* (that's what the `/g` means) occurrences of `__` with `:` and of `;` with `,`.
  * `s/|\([^|]*\)\(|.*\)/|\1\2_\1;/` : the `\(foo\)` construct is called a [capturing group](https://www.regular-expressions.info/brackets.html) and will *capture* `foo` and save it as `\1`, which can be used on the right hand side of the replacement operator. The next captured group will be `\2` then `\3` etc. Here, with `|\([^|]*\)` we are capturing the longest string of non`|` found after the 1st `|` (this happens after the first operation, so the 1st `|` is the one that was 3rd in the original) and then everything after the next `|` (`|.*`) until the end of the line. We then replace everything matched with a `|`, then whatever was matched by the first capture group (`\1`), then the second (`\2`), then we add a `_` and repeat the `\1`.
    Finally, if you want to make the changes to the original input file, use `-i`:
  
    ```
    sed -i.bak 's/>[^|]*|/>/; s/reps|k/tax=d/; s/__/:/g; s/;/,/g; s/|\([^|]*\)\(|.*\)/|\1\2_\1;/; ' file.fa
  
    ```
  
    That will save the original file as `file.fa.bak`. use `-i` alone without any argument if you don't need the backup.
  
  > **Comments:**
  > **username_0**: This works really well, except for two things:  the command changes reps to tax for every other header, and there is still a | in front of tax instead of ;.  
  
  ---
  
  