<p>If your fastq file is simple, if each of your reads only has a single line of DNA, you could do:</p>

<pre><code>awk '{
        if($1 == "@31027"){
            a=NR+1
        } 
        if(NR==a){
            split($0,s,""); 
            s[12]="T"; 
            for(i in s){
                seq = sprintf("%s%s",seq,s[i]);
            } 
            $0=seq
        }
    }1;' file.fastq 
</code></pre>

CC BY-SA 3.0
2017-08-07T11:50:46.357Z
2017-08-07T11:58:19.077Z
2017-08-07T11:58:19.077Z
terdon
<p>You'll first need to determine the appropriate line number, which you can do with <code>grep -m1 -nw "@31027" foo.fastq</code>. After that, note that you can provide a line number to <code>sed</code>:</p>

<pre><code>sed -i '123456s/CAAAAGTCACTCA/CAAAAGTCACTTA/' foo.fastq
</code></pre>

<p>That will do the replacement only on line 123456 and edit the file in place (the <code>-i</code> option).</p>

CC BY-SA 3.0
2017-08-07T23:53:47.327Z
I was not aware of the -n option for grep. This should do the job
dkainer
CC BY-SA 3.0
2017-08-08T08:48:58.360Z
@dkainer just for completion's sake, you can get the line number of the line(s) matching the string `foo` with `sed -n /foo/=` or `perl -ne 'print $. if /foo/` or `awk '/foo/{print NR}` as well.
terdon
CC BY-SA 3.0
2017-08-07T09:52:10.770Z
2017-08-07T11:48:56.240Z
2017-08-07T11:48:56.240Z
Devon Ryan
<p>I am introducing SNVs into specific samples in order to estimate false negative rates for a variant calling pipeline. I know reads can be simulated but I would actually prefer to use the real data so as to keep everything else equal.</p>
<p>Given a read ID, I want to edit a single basecall (e.g. the 12th base) for just that read from within a large FASTQ file containing millions of reads.</p>
<p>example, i want to change the 12th base ('C') in read 31027 to a 'T':</p>
<pre>@70630 1:N:0:ATCACG
GAAGGTCCATGGATAATACTCAATTTTCCACAACAGCTTTTGTACTCTAGATCATTGATATTTACCAAAAGTCACTCAAACTCATCCTATGCATAATTCTAGTCCACCAATCATGATATGATGGAGAACATGGTTGTAATCAGGAAGACAG
+
DDDDDHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIGHHIIIIIIIIIIIIIIIIIIIIIIHIIHIHIIIHHIGIIIIHHHHIIH@
@31027 1:N:0:ATCACG
CAAAAGTCACTCAAACTCATCCTATGCATAATTCTAGTCCACCAATCATGATATGATGGAGAACATGGTTGTAATCAGGAAGACAGATAAAGCAGCAGACCAAAAGTAATCTGAGAAATTATATTTGAATCACTCAGATATACATCAAATA
+
DDBDDHC@GHFHHIIE@CEHHIHEFFCGFCH?HHEGFCCEHHCGH@HFHHHCHHIIIHEHIIHII@CECHIHIIIEECCDGEHFFHHHHEHHFHHGGIHHHDGHFHIIIGHHHHHHEHHIIHIIIGGHHHCHHHCHIIIHHIEH@GHIHIC
@87319 1:N:0:ATCACG
CAATTAAGCTTTGGCAACGGTGGTCAAGATGAGATGCATATGGAGATAATAACTAAAAGTCAATCGAGACTCATCGTATGCATATTTCTAGTCCATCGATCATGAAATGATAGGATAGCTAGAATGAAAAGTAAATTTCCAGAAGGTCCAT
+
DDDDDIIIIIIIIIIIIIHIHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHHIIIIIIIIIIIIIIIIIHIIHIIIIIIIIIIIIHIIIIIIIIIHIHIH
</pre>
<p>Of course I could stream through the entire FASTQ file rewriting everything to a new file until i get to the read of interest, do the edits to that read, write it out to the new file, and then keep going until the end. BioPython would work fine for this as would other approaches.</p>
<p>However, is there an efficient way to do this without the full read/write stream? Could this be done with sed/awk ? What about an indexed fastq file?</p>
<p>cheers
David</p>

<python><ngs><fastq><awk>
How can I edit a specific FASTQ read in place, given the read ID?
# How can I edit a specific FASTQ read in place, given the read ID?

(Asked by: username_0 on 2017-08-07)

I am introducing SNVs into specific samples in order to estimate false negative rates for a variant calling pipeline. I know reads can be simulated but I would actually prefer to use the real data so as to keep everything else equal.
Given a read ID, I want to edit a single basecall (e.g. the 12th base) for just that read from within a large FASTQ file containing millions of reads.
example, i want to change the 12th base ('C') in read 31027 to a 'T':
@70630 1:N:0:ATCACG
GAAGGTCCATGGATAATACTCAATTTTCCACAACAGCTTTTGTACTCTAGATCATTGATATTTACCAAAAGTCACTCAAACTCATCCTATGCATAATTCTAGTCCACCAATCATGATATGATGGAGAACATGGTTGTAATCAGGAAGACAG
+
DDDDDHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIGHHIIIIIIIIIIIIIIIIIIIIIIHIIHIHIIIHHIGIIIIHHHHIIH@
@31027 1:N:0:ATCACG
CAAAAGTCACTCAAACTCATCCTATGCATAATTCTAGTCCACCAATCATGATATGATGGAGAACATGGTTGTAATCAGGAAGACAGATAAAGCAGCAGACCAAAAGTAATCTGAGAAATTATATTTGAATCACTCAGATATACATCAAATA
+
DDBDDHC@GHFHHIIE@CEHHIHEFFCGFCH?HHEGFCCEHHCGH@HFHHHCHHIIIHEHIIHII@CECHIHIIIEECCDGEHFFHHHHEHHFHHGGIHHHDGHFHIIIGHHHHHHEHHIIHIIIGGHHHCHHHCHIIIHHIEH@GHIHIC
@87319 1:N:0:ATCACG
CAATTAAGCTTTGGCAACGGTGGTCAAGATGAGATGCATATGGAGATAATAACTAAAAGTCAATCGAGACTCATCGTATGCATATTTCTAGTCCATCGATCATGAAATGATAGGATAGCTAGAATGAAAAGTAAATTTCCAGAAGGTCCAT
+
DDDDDIIIIIIIIIIIIIHIHHIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIHHIIIIIIIIIIIIIIIIIHIIHIIIIIIIIIIIIHIIIIIIIIIHIHIH

Of course I could stream through the entire FASTQ file rewriting everything to a new file until i get to the read of interest, do the edits to that read, write it out to the new file, and then keep going until the end. BioPython would work fine for this as would other approaches.
However, is there an efficient way to do this without the full read/write stream? Could this be done with sed/awk ? What about an indexed fastq file?
cheers
David

**Tags:** python, ngs, fastq, awk

---

## 2 answers

### Answer by username_2 on 2017-08-07. Score: 5 | Accepted answer

You'll first need to determine the appropriate line number, which you can do with grep -m1 -nw "@31027" foo.fastq. After that, note that you can provide a line number to sed:
sed -i '123456s/CAAAAGTCACTCA/CAAAAGTCACTTA/' foo.fastq

That will do the replacement only on line 123456 and edit the file in place (the -i option).

> **Comments:**
> **username_0**: I was not aware of the -n option for grep. This should do the job  
> **username_1**: @dkainer just for completion's sake, you can get the line number of the line(s) matching the string `foo` with `sed -n /foo/=` or `perl -ne 'print $. if /foo/` or `awk '/foo/{print NR}` as well.  

---

### Answer by username_1 on 2017-08-07. Score: 2

If your fastq file is simple, if each of your reads only has a single line of DNA, you could do:
awk '{
        if($1 == "@31027"){
            a=NR+1
        } 
        if(NR==a){
            split($0,s,""); 
            s[12]="T"; 
            for(i in s){
                seq = sprintf("%s%s",seq,s[i]);
            } 
            $0=seq
        }
    }1;' file.fastq


---

