テキストのパターンマッチ処理に長けたスクリプト言語

awk

awk はテキストのパターンマッチ処理に長けたスクリプト言語である。Perl や Python ほどの機能を持たないが、Linux のコマンドのように使えて、ほんの数行だけで強力なテキストパターンマッチングを発揮できる。

awk を利用したパターンマッチング

awk は、あるパターンにマッチングした時に、それに応じた処理を行うコマンドである。例えば、sample.tsv ファイル中に abc を含む行があれば、それを画面上に出力する場合は以下のようにする。/abc/ のようにパターンを指定し、{print $0} で処理を行う。この場合、$0 を画面上に出力する処理を行っている。$0 は、awk でファイルの 1 行文の内容を表すと定義されている。。

awk '/abc/{print $0}' sample.tsv

タブ区切りのテキストファイル sample.tsv の第 1 列と第 3 列の内容を出力する場合は次のようにする。まず、メインの処理を実行する前に、BEGIN ブロックが処理されて、区切り文字 FS としてタブを \t をセットアップする。次に、print 関数を利用して、ファイルをタブ区切りとみなしたときの、第 1 列と第 3 列を出力する。この場合は、すべての行に対して処理を行うので、パターンを省略する。

awk 'BEGIN{FS="\t"}{print $1, $3}' sample.tsv

awk で 2 列目の数値と 3 列目の数値の和を計算して出力する場合は、次のようにする。

awk '{print $2 + $3}' sample.tsv

各行の内容の前に行番号を追加する場合は次のようにする。

awk '{print NR, $0}' sample.tsv

ファイル中の偶数行だけを出力したい場合は次のようにする。

awk 'NR % 2 == 0 {print $0}' sample.tsv

awk 組み込み変数

awk にはいくつかの組み込み変数が存在する。例えば、現在の処理しているファイルの行数や列数などの情報が組み込み変数に保存されている。

組み込み変数機能
$0ファイル1行(レコード)分の内容。
$n現在の行の、n 番目のカラム(フィールド)のテキスト内容。
RSフィールドの区切り文字。デフォルトは改行文字。
FS1 行のテキストをカラムに分割する際に利用する区切り文字。
OFSFS と同じく区切り文字を表します。OFS は処理結果を出力するときの区切り文字として利用される。
NF現在のカラム数(区切り文字で区切った時にできる列数)
NR現在の行数

awk の応用例

CSV ファイルはカンマで規則正しく区切られたファイルであり、awk を利用して簡単にデータを抽出したり、加工したりすることができる。

data.csv を読み込んで、各列の平均を出力する場合は次のようにする。

awk '
  BEGIN{
    FS = ","
  }
  {
    for (i = 1; i <= NF; i++) {
      s[i] += $i
    }
  }
  END{
    for (i = 1; i <= NF; i++) {
      print s[i] / NR
    }
  }' data.csv

各列の絶対値を出力する場合は次のようする。

awk '
   BEGIN{
      FS = ","
   }
   {
      for(i = 1; i <= NF; i++){
         ($i < 0) ? $i = -$i : $i = $i
      }
      print $0
   }
' data.csv

1 列目のデータを、小数 4 桁で表示する例。

awk 'BEGIN{FS=","}{printf("%.4f\n",$1)}' data.csv

awk で利用できる正規表現

awk(gawk v3.0)で利用できる正規表現。

grepsedawk
...
***
^^^
$$$
¥( ¥)¥( ¥)( )
\1 \2 \3\1 \2 \3\1 \2 \3
[ ][ ][ ]
¥{n, m¥}¥{n, m¥}{n, m}
¥{n, ¥}¥{n, ¥}{n, }
¥{n¥}¥{n¥}{n}
\+\++
\??
\|\||

バイオインフォマティクス

FASTQ to FASTA

awk コマンドを使用して FASTQ ファイルを FASTA ファイルに変更する方法。具体的には、FASTQ 各エントリーの最初の 2 行を出力して、そして、先頭にある @ を > に変更している。

awk 'NR % 4 == 1 || NR % 4 == 2' ./sample.fq | sed 's/^@/>/'
## >SRR1976499.1 HWI-ST957:247:D1V5GACXX:3:1101:1209:1967 length=50
## NTTATGACTATACCGTCATTCTCTTGGTTAGATCAGTTTTCACAATCCTT
## >SRR1976499.2 HWI-ST957:247:D1V5GACXX:3:1101:1288:1984 length=50
## NAGAGGACAAGATCCTCCACTAATTTCACAAAAAGCTCATCTTTTTATTC
## >SRR1976499.3 HWI-ST957:247:D1V5GACXX:3:1101:1708:1966 length=50
## NCAACACCATCGACGGTGATAGGCCTTGGAGGATCATCCATCACCACCAA
## >SRR1976499.4 HWI-ST957:247:D1V5GACXX:3:1101:1659:1970 length=50
## NATAAGGTCTTTTTCCGTTTCCTTGACCTCTCTGGGATTTGGATTTCGAT
## >SRR1976499.5 HWI-ST957:247:D1V5GACXX:3:1101:1602:1995 length=50
## NCGAAGCTTACAACGAGTTACACGCTTTGGCGCAGGAATTGGAGACGCCG

FASTQ から特定エントリーの抽出

FASTQ ファイルから特定のエントリーを抽出する方法。次のサンプルは、sample.fq ファイルから「@SRR1976499.6 HWI」を含むエントリーを出力例となっている。

awk '/^@SRR1976499.6 HWI/{i=4}{if(i){i--; print $0}}' sample.fq
## @SRR1976499.6 HWI-ST957:247:D1V5GACXX:3:1101:2114:1961 length=50
## NTGAAGGTTGGGAAAGATTCAAAAGACAAGGAGCTGAAGGAAGCATTCAA
## +SRR1976499.6 HWI-ST957:247:D1V5GACXX:3:1101:2114:1961 length=50
## #1=BDDFDHHGGHIIJJJJIIJJIGJJJJJJGHEGIJIJJJIJIJJJIJG

FASTQ からダウンサンプリング

次の awk サンプルは、FASTQ ファイルから 20% のエントリーを抽出する例である。

awk 'BEGIN{srand('"$RANDOM"')} {if(NR>1&&NR%4==1){if(rand()<0.02){print s} s=$0}else{s=s"\n"$0}}' sample.fq | head
## @SRR1976499.16 HWI-ST957:247:D1V5GACXX:3:1101:3662:1963 length=50
## NAATTCGAAGAGAACAACAGTACACCGAATTTGACATTGAGATACTTTCC
## +SRR1976499.16 HWI-ST957:247:D1V5GACXX:3:1101:3662:1963 length=50
## #1=DFFFFHHHHHJJJJJIJIIJJJJJJJJJJJJJJJJIJJJJJJJJJJJ
## @SRR1976499.72 HWI-ST957:247:D1V5GACXX:3:1101:16189:1970 length=50
## NAAATACTCTCCGGAGTTAACTACGCTTCCGCAGCTGCTGGAATCCGAGA
## +SRR1976499.72 HWI-ST957:247:D1V5GACXX:3:1101:16189:1970 length=50
## #1=DFFFFHHHHHJJIGHJJIIJIIJJJJJJJJIJJFJJJJJIIJIJJII
## @SRR1976499.84 HWI-ST957:247:D1V5GACXX:3:1101:19256:1971 length=50
## NTTTTAGTGATTTCTGAAAATTTCGGAATCTTCCAAGTATACTGTCCATA