Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-07T11:50:46.357Z
Answers.LastActivityDate: 2017-08-07T11:58:19.077Z
Answers.LastEditDate: 2017-08-07T11:58:19.077Z
Answers.UserDisplayName: terdon
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-07T23:53:47.327Z
Answers.Text: I was not aware of the -n option for grep. This should do the job
Answers.UserDisplayName: dkainer
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-08T08:48:58.360Z
Answers.Text: @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.
Answers.UserDisplayName: terdon
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-08-07T09:52:10.770Z
Answers.LastActivityDate: 2017-08-07T11:48:56.240Z
Answers.LastEditDate: 2017-08-07T11:48:56.240Z
Answers.UserDisplayName: Devon Ryan
Body: <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>
  
Tags: <python><ngs><fastq><awk>
Title: How can I edit a specific FASTQ read in place, given the read ID?
ThreadText: # 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**: @username_0 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 
  
  ```
  
  
  ---
  
  