<p>I like using <code>awk</code> when there's any kind of lookup involved: something like</p>

<pre><code>awk 'FNR==NR {
    hash["&gt;"$1]=$2;
    next;
}

if ($1 ~ /^&gt;/) {
    print "&gt;"hash[$1];
} else {
    print $1;
}' keyValues.txt mySequence.fasta
</code></pre>

<p>Basically the <code>FNR==NR</code> check tells awk to work only on the first file (useful primer <a href="https://stackoverflow.com/questions/32481877/what-is-nr-fnr-in-awk">here</a>), <code>keyValues.txt</code> and create an association for each key (eg. <code>chr_I</code>) with its value (eg. <code>I</code>). The rest of the code after the <code>next</code> works only on <code>mySequence.fasta</code>, printing out the lookup value only if the line is a fasta header, as checked by the <code>$1 ~ /^&gt;/</code> condition. </p>

CC BY-SA 4.0
2018-06-27T17:41:48.223Z
2018-06-27T17:41:48.223Z
flatley176
<p>Your issue is that the pattern <code>.</code> matches a single character. To match the whole header, use <code>.*</code>:</p>
<pre class="lang-sh prettyprint-override"><code>seqkit replace -p &quot;(.*)&quot; --replacement &quot;{kv}&quot; --kv-file keyValues.txt mySequence.fasta
</code></pre>
<p>Alternatively as pointed out by others you may not really need <code>keyValues.txt</code> here as you're just removing the <code>chr_</code> prefix:</p>
<pre class="lang-sh prettyprint-override"><code>seqkit replace -p &quot;chr_(.*)&quot; --replacement '$1' mySequence.fasta
</code></pre>
<p>(Don't forget the single quotes for <code>$1</code> else the shell will expand it)</p>

CC BY-SA 4.0
2023-04-22T07:55:29.393Z
2023-04-22T07:55:29.393Z
bricoletc
<p>Here is an alternative to sed: <code>cat test | tr -d "chr_"</code></p>

<p>The pipe is to output the file, while the <code>tr</code> command is to translate and change the file</p>

CC BY-SA 4.0
2018-06-25T10:20:09.410Z
The use of the `cat` command is completely redundant here (and imposes a runtime overhead). Just do `tr -d 'chr_' < test`.
Konrad Rudolph
CC BY-SA 4.0
2018-06-24T17:38:12.380Z
2018-06-25T07:58:30.013Z
2018-06-25T07:58:30.013Z
aerijman
<p>Why not use <code>sed</code> instead?</p>

<pre><code>sed -e 's/chr_I/I/' -e 's/chr_V/V/' -e 's/chr_X/X/' mySequence.fasta &gt; mySeq.fasta
</code></pre>

<p>Or even simpler:</p>

<pre><code>sed 's/chr_//' mySequence.fasta &gt; mySeq.fasta
</code></pre>

CC BY-SA 4.0
2018-06-21T12:12:24.260Z
Worked. I just don't know `sed`. I need to learn it.
Biomagician
CC BY-SA 4.0
2018-06-21T12:16:30.090Z
Great! It works a bit like `grep` (which you know how to use), but then with replacement function.
benn
CC BY-SA 4.0
2018-06-21T16:00:07.283Z
I would suggest using `sed 's/^chr_//'` instead. Anchoring the pattern to the beginning of the line should speed things up for large files. Otherwise, `sed` will have to scan the entire length of each line in case there's a match.
terdon
CC BY-SA 4.0
2018-06-21T17:21:57.323Z
@terdon, good point. But does it work with fasta? Remember the `>` at the beginning of the header.
benn
CC BY-SA 4.0
2018-06-21T22:09:10.217Z
@b.nota Duh! I should learn to read :) Indeed, `sed 's/^>chr_/>/` would be better.
terdon
CC BY-SA 4.0
2018-06-22T05:46:39.750Z
Minor correction for the last: `sed 's/^>chr_/>/'` ( in order to keep the `>`)
Sebastian Müller
CC BY-SA 4.0
2018-06-21T12:09:36.550Z
2018-06-21T12:39:35.483Z
2018-06-21T12:39:35.483Z
benn
<p>I am trying to use the <a href="https://bioinf.shenwei.me/seqkit/usage/#replace" rel="noreferrer">seqkit replace</a> command to replace chromosome names in the format <code>chr_I, chr_II, ...</code> to <code>I, II, ...</code>. I am using the following command:</p>
<pre><code>seqkit replace -p &quot;(.)&quot; --replacement &quot;{kv}&quot; --kv-file keyValues.txt mySequence.fasta
</code></pre>
<p>My <code>keyValues.txt</code> file contains the following:</p>
<pre><code>chr_I   I
chr_II  II
...
</code></pre>
<p>The two columns are separated by a tabulation.</p>
<p>I get the following output:</p>
<pre><code>[INFO] read key-value file: keyValues.txt
[INFO] 6 pairs of key-value loaded
[ERRO] pattern &quot;(.)&quot; matches multiple targets in &quot;chr_I&quot;, this will cause chaos
</code></pre>
<p>I don't know what I am doing wrong. I chose the <code>(.)</code> pattern to match the whole header but it seems to be wrong. Any help would be appreciated.</p>
<h3>Update</h3>
<p>All the headers are shown below:</p>
<pre><code>grep '&gt;' mySequence.fasta
&gt;chr_I
&gt;chr_II
&gt;chr_III
&gt;chr_IV
&gt;chr_V
&gt;chr_X
</code></pre>

CC BY-SA 4.0
2018-06-21T10:38:48.360Z
Show some of the headers, the pattern argument is probably not suitable. I am guessing that you'll get headers with duplicate names now (which `will cause chaos`).
benn
CC BY-SA 4.0
2018-06-21T11:25:01.887Z
I have written all the header names in my question.
Biomagician
CC BY-SA 4.0
2018-06-21T11:38:43.830Z
There are 4 matches to your pattern "chr_I"
benn
CC BY-SA 4.0
2018-06-21T12:10:31.913Z
Oh, so the key is a regular expression? I tried putting a dollar at the end of the key names, but I get the same error.
Biomagician
<fasta>
How do I rename fasta headers?
# How do I rename fasta headers?

(Asked by: username_0 on 2018-06-21)

I am trying to use the seqkit replace command to replace chromosome names in the format chr_I, chr_II, ... to I, II, .... I am using the following command:
seqkit replace -p "(.)" --replacement "{kv}" --kv-file keyValues.txt mySequence.fasta

My keyValues.txt file contains the following:
chr_I   I
chr_II  II
...

The two columns are separated by a tabulation.
I get the following output:
[INFO] read key-value file: keyValues.txt
[INFO] 6 pairs of key-value loaded
[ERRO] pattern "(.)" matches multiple targets in "chr_I", this will cause chaos

I don't know what I am doing wrong. I chose the (.) pattern to match the whole header but it seems to be wrong. Any help would be appreciated.
Update
All the headers are shown below:
grep '>' mySequence.fasta
>chr_I
>chr_II
>chr_III
>chr_IV
>chr_V
>chr_X

**Tags:** fasta
> **Comments:**
> **username_1**: Show some of the headers, the pattern argument is probably not suitable. I am guessing that you'll get headers with duplicate names now (which `will cause chaos`).  
> **username_0**: I have written all the header names in my question.  
> **username_1**: There are 4 matches to your pattern "chr_I"  
> **username_0**: Oh, so the key is a regular expression? I tried putting a dollar at the end of the key names, but I get the same error.  

---

## 4 answers

### Answer by username_1 on 2018-06-21. Score: 10 | Accepted answer

Why not use sed instead?
sed -e 's/chr_I/I/' -e 's/chr_V/V/' -e 's/chr_X/X/' mySequence.fasta > mySeq.fasta

Or even simpler:
sed 's/chr_//' mySequence.fasta > mySeq.fasta

> **Comments:**
> **username_0**: Worked. I just don't know `sed`. I need to learn it.  
> **username_1**: Great! It works a bit like `grep` (which you know how to use), but then with replacement function.  
> **username_6**: I would suggest using `sed 's/^chr_//'` instead. Anchoring the pattern to the beginning of the line should speed things up for large files. Otherwise, `sed` will have to scan the entire length of each line in case there's a match.  
> **username_1**: @terdon, good point. But does it work with fasta? Remember the `>` at the beginning of the header.  
> **username_6**: @b.nota Duh! I should learn to read :) Indeed, `sed 's/^>chr_/>/` would be better.  
> **username_7**: Minor correction for the last: `sed 's/^>chr_/>/'` ( in order to keep the `>`)  

---

### Answer by username_2 on 2018-06-27. Score: 2

I like using awk when there's any kind of lookup involved: something like
awk 'FNR==NR {
    hash[">"$1]=$2;
    next;
}

if ($1 ~ /^>/) {
    print ">"hash[$1];
} else {
    print $1;
}' keyValues.txt mySequence.fasta

Basically the FNR==NR check tells awk to work only on the first file (useful primer here), keyValues.txt and create an association for each key (eg. chr_I) with its value (eg. I). The rest of the code after the next works only on mySequence.fasta, printing out the lookup value only if the line is a fasta header, as checked by the $1 ~ /^>/ condition.


---

### Answer by username_3 on 2023-04-22. Score: 1

Your issue is that the pattern . matches a single character. To match the whole header, use .*:
seqkit replace -p "(.*)" --replacement "{kv}" --kv-file keyValues.txt mySequence.fasta

Alternatively as pointed out by others you may not really need keyValues.txt here as you're just removing the chr_ prefix:
seqkit replace -p "chr_(.*)" --replacement '$1' mySequence.fasta

(Don't forget the single quotes for $1 else the shell will expand it)


---

### Answer by username_4 on 2018-06-24. Score: 1

Here is an alternative to sed: `cat test | tr -d "chr_"`

The pipe is to output the file, while the `tr` command is to translate and change the file

> **Comments:**
> **username_5**: The use of the `cat` command is completely redundant here (and imposes a runtime overhead). Just do `tr -d 'chr_' < test`.  

---

