Answers.Body: <p>This script is wrong because a quality string may start with <code>@</code>. With bioawk, it can be simplified to:</p>
  
  <pre><code>bioawk -c fastx '{ readlength[length($seq)]++; countread++ } END{...}'
  </code></pre>
  
  <p>The <code>END{}</code> block is the same as your original version.</p>
  
  <p>EDIT: forgot <code>-c fastx</code> is the original answer. Thank @MattBashton for pointing this out.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-20T15:34:51.747Z
Answers.Text: Using the exact same END{} code from the OP fails in this example with `bioawk: illegal field $(), name "seq"`
Answers.UserDisplayName: Matt Bashton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-20T12:03:30.090Z
Answers.LastActivityDate: 2018-08-20T15:49:32.900Z
Answers.LastEditDate: 2018-08-20T15:49:32.900Z
Answers.UserDisplayName: user172818
Answers.Body: <p>This can also be done with regular awk.</p>
  
  <pre><code>awk '{if(NR%4==2) {count++; bases += length} } END{print bases/count}' &lt;fastq_file&gt;
  </code></pre>
  
  <p>The <code>NR%4==2</code> count the second line out of every block of 4.  <code>length</code> is a built-in that defaults to the length of the line, same as <code>length($0)</code>.  In this case you can inject you custom printing to the <code>END{}</code> block but <code>countread</code> and <code>countstored</code> will always be the same since the averaging is done on the fly.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-20T18:01:08.877Z
Answers.Text: Note that, like OP’s code, this will only work on FASTQ files that don’t break the sequence and/or quality string across multiple lines.
Answers.UserDisplayName: Konrad Rudolph
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-20T22:04:37.853Z
Answers.Text: That is correct.  However that practice is highly frowned upon so should not be an issue with most FASTQ files
Answers.UserDisplayName: Bioathlete
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-21T09:43:46.737Z
Answers.Text: I've yet to ever encounter a FASTQ file which has sequence or quality on multiple lines, I think for all intensive purposes assuming 4 lines per record should be fine.
Answers.UserDisplayName: Matt Bashton
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2018-08-20T14:43:26.193Z
Answers.LastActivityDate: 2018-08-20T14:43:26.193Z
Answers.UserDisplayName: Bioathlete
Body: <p>I found <a href="http://cagt.bu.edu/w/images/8/81/Avg_read_len_fastq.awk" rel="nofollow noreferrer">here</a> this awk script: </p>
  
  <pre><code>BEGIN {
    headertype="";
    }
  {
    if($0 ~ "^@") {
      countread++;
      headertype="@";
    }
    else if($0 ~ "^+") {
      headertype="+";
    }
    else if(headertype="@") { # This is a nuc sequence
      len=length($0);
      if (len&gt;4) {
        readlength[len]++;
      }
    }
  }
  END {
    for (i in readlength){
      countstored+=readlength[i];
      lensum+=readlength[i]*i;
      print i, readlength[i];
    }
    print "reads read = "countread &gt; "/dev/stderr";
    print "reads stored = "countstored &gt; "/dev/stderr";
    print "read average length = "lensum/countstored &gt; "/dev/stderr";
  }
  </code></pre>
  
  <p>and I just wonder if it is possible to shorten it with bioawk?</p>
  
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2018-08-19T10:49:32.527Z
Comments.Text: It might be possible.  What problem do you have with having a long script? Why do you want a shorter script? Or do you want a faster script?
Comments.UserDisplayName: llrs
Comments.ContentLicense: CC BY-SA 4.0
Comments.CreationDate: 2021-12-17T08:37:19.907Z
Comments.Text: Did anyone get the correct script for finding out the average read length?
Comments.UserDisplayName: Saraswati Awasthi
Tags: <fastq><awk><bioawk>
Title: Calculating read average length in a Fastq file with bioawk/awk
ThreadText: # Calculating read average length in a Fastq file with bioawk/awk
  
  (Asked by: username_0 on 2018-08-18)
  
  I found [here](http://cagt.bu.edu/w/images/8/81/Avg_read_len_fastq.awk) this awk script:
  
  ```
  BEGIN {
    headertype="";
    }
  {
    if($0 ~ "^@") {
      countread++;
      headertype="@";
    }
    else if($0 ~ "^+") {
      headertype="+";
    }
    else if(headertype="@") { # This is a nuc sequence
      len=length($0);
      if (len>4) {
        readlength[len]++;
      }
    }
  }
  END {
    for (i in readlength){
      countstored+=readlength[i];
      lensum+=readlength[i]*i;
      print i, readlength[i];
    }
    print "reads read = "countread > "/dev/stderr";
    print "reads stored = "countstored > "/dev/stderr";
    print "read average length = "lensum/countstored > "/dev/stderr";
  }
  
  ```
  
  and I just wonder if it is possible to shorten it with bioawk?
  
  **Tags:** fastq, awk, bioawk
  
  > **Comments:**
  > **username_1**: It might be possible.  What problem do you have with having a long script? Why do you want a shorter script? Or do you want a faster script?  
  > **username_2**: Did anyone get the correct script for finding out the average read length?  
  
  ---
  
  ## 2 answers
  
  ### Answer by username_5 on 2018-08-20. Score: 8 | Accepted answer
  
  This can also be done with regular awk.
  
  ```
  awk '{if(NR%4==2) {count++; bases += length} } END{print bases/count}' <fastq_file>
  
  ```
  
  The `NR%4==2` count the second line out of every block of 4. `length` is a built-in that defaults to the length of the line, same as `length($0)`. In this case you can inject you custom printing to the `END{}` block but `countread` and `countstored` will always be the same since the averaging is done on the fly.
  
  > **Comments:**
  > **username_6**: Note that, like OP’s code, this will only work on FASTQ files that don’t break the sequence and/or quality string across multiple lines.  
  > **username_5**: That is correct.  However that practice is highly frowned upon so should not be an issue with most FASTQ files  
  > **username_4**: I've yet to ever encounter a FASTQ file which has sequence or quality on multiple lines, I think for all intensive purposes assuming 4 lines per record should be fine.  
  
  ---
  
  ### Answer by username_3 on 2018-08-20. Score: 3
  
  This script is wrong because a quality string may start with `@`. With bioawk, it can be simplified to:
  
  ```
  bioawk -c fastx '{ readlength[length($seq)]++; countread++ } END{...}'
  
  ```
  
  The `END{}` block is the same as your original version.
  
  EDIT: forgot `-c fastx` is the original answer. Thank @username_4 for pointing this out.
  
  > **Comments:**
  > **username_4**: Using the exact same END{} code from the OP fails in this example with `bioawk: illegal field $(), name "seq"`  
  
  ---
  
  