生命情報科学専門自習2 Perl を使わないでテキスト処理
2. フィルタによるテキスト処理
2 回生前期の実習でプログラミング言語 Perl を学んだ1。しかし、簡単なテキス ト処理は長いプログラムを作成するまでもなく、UNIX のコマンドを複数組み合わせるだ けで実現できることが多い。 入力されたテキストを加工して出力するコマンドをフィルタと呼ぶことがある。 UNIX にはフィルタが多数用意されている。今日の実習では、フィルタの便利な使いかた と、複数のフィルタの連携技を練習する。2.a. pdb から座標データをダウンロード
テキスト処理の練習台として、PDB から 2 つの立体構造ファイルをダウンロード しよう。 1. 端末ウィンドウを開き、前回の実習で作成した、ディレクトリ works/db/pdb へ移 動する。 2. FireFox を起動し、PDB へ行き、1CLL をダウンロード。ダウンロードしたファイ ルを上記のディレクトリへ移動させる。 3. 次に、PDB から 1UAO をダウンロード。同様に移動させる。2.b. リダイレクションとパイプの復習
リダイレクションは、UNIX の重要かつ便利な機能である。2 回生前期の実習でも 習ったが、復習しておく。 1 Perl の特徴はテキスト処理が得意なことであり、それゆえ、バイオインフォマティクスに適している。①
入力 cat input.txt input.txt②
処理( cat の場合:受け取っ たデータをそのまま吐き出す)③
標準出力への吐き出し cat多くのコマンドやソフトウェアは、①なんらかの情報を受け取り、②処理し、③ 結果を出力する(前ページの図)。 cat の処理結果は端末ウィンドウに表示されるが、これは cat が結果を標準出力に 吐き出した(出力した)からである。通常、標準出力に吐き出された情報は端末ウィンドウ に表示されるようになっている。また、多くのコマンドは、ファイルからだけでなく、標 準入力という経路からも入力データを受け付ける。特に指定しない場合、キーボードでタ イプした文字列が標準入力に流れ込むようになっていることが多い。 コマンドが結果を標準出力に吐き出す性質を利用すると、リダイレクションによっ て、その結果を新しいファイルに格納したり、既存のファイルの末尾に付け加えたりする ことができる。リダイレクト(redirect)とは、「・・・のあて名を変える」という意味 だ。 標準出力に吐き出された内容を新しいファイルに格納するには > を利用する。例 えば、old_file.txt の内容を cat を用いて new_file.txt に書き込むには、端末ウィンドウの プロンプトに対して次のようにする。
cat old_file.txt > new_file.txt (cat を使ってテキストファイルをコピー) このとき、cat の出力は new_file.txt へリダイレクトされているので、端末ウィンドウに は表示されない。
標準出力を既存のファイルの末尾につなげるように格納するには、>> を利用する。 例えば、another_file.txt の中身を、先ほど作られた new_file.txt の末尾に追加するには、 次のようにする。
cat another_file.txt >> new_file.txt
(cat を使って、another_file.txt の内容を new_file.txt の末尾に付加)
コマンドが標準出力へ吐き出した結果を、端末ウィンドウやファイルではなく、 別のコマンド(やプログラム)の標準入力に流し込むこともできる。この機能をパイプと いう。 パイプを利用するときは | (縦棒)を使う。例えば、ls l で表示されるファイル のリストの全てではなく、”txt”を含むファイル名の情報だけを表示させたいときには次 のようにする。これの結果と、単にls l を実行したときの結果とを比較してみよう。 ls -l | grep txt なお、grep は、入力データ(ファイルまたは標準入力)の中から、指定した文字列 を含む行のみを抜き出して表示する(標準出力へ吐き出す)コマンドである(後述)。
パイプの機能
2.c. ワイルドカード
シェルでは、ファイル名の指定のために、ワイルドカード(*) を使うことができ る。例えば、次のように使う。 ls -l *.pdb (カレントディレクトリにある、ファイル名の末尾が .pdb であるファイル全て のリストの表示) rm * (全てのファイルを削除。危険なので安易に実行しないこと) mv dir1/*.fasta dir2/(ディレクトリ dir1 にある、ファイル名の末尾が .fasta のファイルを全て dir2 へ移動) more *genome* (ファイル名に genome を含む全てのファイルを(1 ページずつ)表示) * は任意の文字列の代替になるワイルドカードだが、任意の1文字の代替になる ワイルドカードとして、? がある。例えば、次のように使う。 ls ?? (2 文字のファイル名を全て表示) rm x?? (ファイル名の先頭が x の、3文字のファイル名のファイルを全て削除) ls l grep パイプ 標 準 出 力 端末ウィンドウ 標 準 入 力 標 準 出 力 端末ウィンドウ 表示 ls -l | grep txt
2.d. テキスト関連の UNIX コマンド (フィルタ)
2.d.1. cat
ファイルの中身を表示するコマンドcat が、ファイルの連結に使えることは以前説 明したとおりである。例えば、次のような便利な使い方ができる。2
cat seq1.fasta seq2.fasta seq3.fasta > seqs_123.fasta
(seq1.fasta と seq2.fasta と seq3.fasta の内容を順につなぎ、seqs_123.fasta に 出力)
cat seq*.fasta > all_seqs.fasta
(ファイル名が seq ではじまり、.fasta で終わる全てのファイルを順番に3
連結し、 all_seqs.fasta というマルチ FASTA 形式のファイルを作る)
cat model5.pdb >> models.pdb
(model5.pdb の内容を、models.pdb の末尾に追加) 2.d.2. head, tail head は、入力されたテキストの最初の 10 行のみを表示する。表示する行の数を 変えることもできる。例えば、次のように使う。 head 1CLL.pdb (1CLL.pdb の最初の 10 行を表示) tail 1CLL.pdb (1CLL.pdb の最後の 10 行を表示) head -1 seq*.txt (ファイル名が seq で始まり、.txt で終わる全てのファイルの 1 行目を(全て)表示) tail -23 1CLL.pdb (1CLL.pdb の最後の 23 行を表示) 2 そのほかの便利機能として、n オプション (行番号を付加して表示) がある。 3 ファイル名のアルファベット順
2.d.3. grep grep は、指定された文字列を含む行だけを表示する。例えば、次のように使う。 検索文字列では正規表現を使うこともできる。また、n オプションを使うと、それが入 力の何行目か、を表す数字も表示される。 grep CA 1CLL.pdb (1CLL.pdb で、文字列「CA」を含む行4のみを表示。) grep “>” seqs_123.fasta (> を含む行のみを表示。シェルがリダイレクションのための>として解釈して しまうことを防ぐために、引用符が必要。)
grep ‘^SEQRES’ 1UAO.pdb
(1UAO.pdb で、行頭が SEQRES の行のみを表示)
grep -n ‘^SEQRES’ 1UAO.pdb
(1UAO.pdb で、行頭が SEQRES の行のみを表示。それが何行目かも表示) 2.d.4. wc wc は、入力された文字の総数とか、行の総数とか、単語の個数を表示するコマン ドである。ここでは、行の総数を表示させる l オプションを使う例のみをあげる。 wc -l 1UAO.pdb (1UAO.pdb の行数を表示)
grep "^ENDMDL " 1UAO.pdb | wc -l
(1UAO.pdb に含まれる ENDMDL 行の個数 (=含まれる構造モデルの個数)を表 示。^は、ENDMDL が行頭にあるときにだけマッチさせるためのおまじない)
2.d.5. diff diff は、指定された 2 つのファイルを比較し、どこが異なるか、を指摘する。2つ のファイルの内容がまったく同一なら、何も表示しない。 diff ファイル1 ファイル2 2.d.6. sort sort は、入力されたテキストの行の順序をソートする。通常は行の内容が文字コー ド順 (ほぼアルファベット順) になるように並べ替える。行全体を見て比較するのではな く、フィールドのみを比較したいときには k オプションを、文字コードとしてではなく、 数値として比較したいときには n オプションをつける。 今、右のような内容のhanshin.txt というファイルがあるとする。 このデータファイルに対するsort コ マンドのいろいろな実行例を挙げる。 sort hanshin.txt (文字列として行と行を比較す るので、4, 6 よりも 24, 39 の 方が上になる。) この結果をあとで使うのでファイルに保存しておこう。フィルタの実行結果を保 存するときには次のようにしてリダイレクションを使えばよい。次の例では、結果がhan shin5.txt というファイルに保存される。
sort hanshin.txt > hanshin5.txt
53 Akahoshi 0.319 1 Toritani 0.276 4 Sheets 0.290 7 Imaoka 0.281 6 Kanemoto 0.325 39 Yano 0.274 9 Fujimoto 0.251 24 Hiyama 0.278 hanshin.txt 1 Toritani 0.276 24 Hiyama 0.278 39 Yano 0.274 4 Sheets 0.290 53 Akahoshi 0.319 6 Kanemoto 0.325 7 Imaoka 0.281 9 Fujimoto 0.251 hanshin5.txt
sort -b -k 2,2 hanshin.txt (第 2 フィールドの人名の順序にソートする。k 2,2 は、オプションで2つめのフィールドを指定 するときの正式な方法である5。フィールド同士 を隔てる空白文字の個数が統一されていないファ イルに対して k オプションを適用する場合は、 b オプションを併用した方がよい。6) sort -n -k 3,3 hanshin.txt (第 3 フィールドの打率を数値的に比較して、 低い順にソートする。7 ) sort -n -k 3,3 -r hanshin.txt (打率の大きい順にソートする。-r を指定す ると、並べる順序が逆順になる。) sort コマンドには他にもたくさんのオプションが用意されている。man sort を参 照のこと。 2.d.7. uniq uniq は、前後の行を比較して、まったく同じ内容 の行が連続していたら、1つを残して他を削除する。uni q を利用する前に sort を使うことによって、応用の幅が ひろがる。 次の例は、右に示す入力データに対してuniq を実 行した結果である。 5 この例では、k 2 のように簡略表記できる。しかし、n オプションと併用するときには本文に示したよ うに書かないと、思わぬ結果が得られる場合がある。 6 詳しくは man sort を参照のこと。 7 この例から分かるように、n オプションを使うと、数値の小さい順のソートになる。 53 Akahoshi 0.319 9 Fujimoto 0.251 24 Hiyama 0.278 7 Imaoka 0.281 6 Kanemoto 0.325 4 Sheets 0.290 1 Toritani 0.276 39 Yano 0.274 6 Kanemoto 0.325 53 Akahoshi 0.319 4 Sheets 0.290 7 Imaoka 0.281 24 Hiyama 0.278 1 Toritani 0.276 39 Yano 0.274 9 Fujimoto 0.251 9 Fujimoto 0.251 39 Yano 0.274 1 Toritani 0.276 24 Hiyama 0.278 7 Imaoka 0.281 4 Sheets 0.290 53 Akahoshi 0.319 6 Kanemoto 0.325 This is a pen. It is a pencil. It is a pen. This is a pin. This is a pen. This is a pencil. eibun.txt
uniq eibun.txt
(結果は、eibun.txt と同じ。)
次の例は、パイプを使ったsort と uniq の連携技の例である。 This is a pen. という行が一行だけになったことに注目。
sort eibun.txt | uniq
(sort してから uniq を実行した。)
2.d.8. join
join は、2 つの表形式のファイルを横方向に連結する8。使いこなせばとても便利。
join data1.txt data2.txt
2.d.9. paste paste は、join の低機能版で、機械的に同じ行番号の行同士を横に連結する。また、 s オプションを付けると、入力ファイルから改行コードを削除する。 paste -s data1.txt (data1.txt から改行を取り除く) 8 デフォルトでは、両方のファイルの第 1(最左の)フィールド同士が一致する行同士を横方向に連結する。 このとき2 つめのファイルの第 1 フィールドは削られる。また、join を使うときには、事前に、両方の入 力ファイルを sort b でソートしておくこと。詳しくは、man join を参照。 join It is a pen. It is a pencil. This is a pen. This is a pencil. This is a pin. 1 100 2 200 3 300 4 400 5 500 1 one 2 two 3 three 4 four 5 five data1.txt data2.txt + 1 100 one 2 200 two 3 300 three 4 400 four 5 500 five 1 100 2 200 3 300 4 400 5 500 This is a pen. It is a pencil. It is a pen. This is a pin. This is a pen. This is a pencil.
2.d.10. split split は、入力ファイルを指定した行数の断片に分割し、その断片を新しいファ イルに書き込む。9 split -100 1UAO.pdb (1UAO.pdb の内容を 100 行毎に分割し、結果をそれぞれ新しいファイルに格納) 2.d.11. cut cut は、入力データの各行から、指定された領域だけを取り出して表示する。c オ プションを使うと、各行の左から数えて何文字目(から何文字目まで)を表示するかを指定 できる。10 cut -c18-20 1CLL.pdb (1CLL.pdb の各行の、左から 18 文字目から 20 文字目までを表示。実際に実行し てみよ。1UAO.pdb についてもやってみよ。)
2.e 課題 1
以下の問に答えよ。 第1問 マルチFASTA 形式のファイル(ファイル名は multi.fasta とする)から、ヘッダ行 のみを取り出して表示するためのコマンド文字列を書け。 第2問 1UAO.pdb から、アミノ酸配列の情報が記されている、SEQRES レコードのみを 取り出して表示するためのコマンド文字列を書け。 第3問 1UAO.pdb から、原子座標が書かれている ATOM レコードのみを取り出して表示 するためのコマンド文字列を書け。 第4問 1CLL.pdb に HETATM レコードが何行あるかを知るためのコマンド文字列を書 9 新しくできるファイルの名前は、xaa, xab, xac のようになる。これの変え方などは、man split を参照。 10 他のオプションについては、man cut を参照。け。パイプを使うとよい。 第5問 1UAO.pdb の ATOM レコードのうち、α 炭素のレコードのみを取り出して表示す るためのコマンド文字列を書け。 第6問 このファイルのタンパク質のアミノ酸配列を表示するコマンド文字列を書け。ま ず、α 炭素のATOM レコードだけを取り出すコマンド文字列を書き、パイプで他のコマ ンドにつなげると良い。 第7問 1CLL.pdb に含まれるアラニンの個数を知るためのコマンド文字列を書け。 第8問 第6 問で、アミノ酸配列を 1 行で(つまり、改行コードを含まずに)表示するための コマンド文字列を書け。 第9問 1UAO.pdb の ATOM レコードに記されている原子の x 座標の最小値を知るための コマンド文字列を書け。 第10問 1UAO.pdb の第 500 行から第 520 行までを表示するコマンド文字列を書け。head やtail をうまく組み合わせること。 第11問 第10 問で、1UAO.pdb における行番号も一緒に表示するにはどうすればよいか。 第12問 第6 問のコマンド文字列を編集して、1CLL.pdb に含まれるアミノ酸の組成(どの アミノ酸が何個あるか)を表示するコマンド文字列を書け。最後に、uniq コマンドをc オ プションとともに使う11とよい。 11 そうするとどうなるのか、は、man uniq で確認せよ。
第13問
4 ページで登場した hanshin5.txt と、次に示す hanshin6.txt をもとにして、hans hin4.txt のような表を作るコマンド文字列を書け。 第14問 1UAO.pdb の ATOM レコードのうち、原子の y 座標が負の数である行だけを表示 するコマンド文字列を書け。
3. awk 入門
課題1 の最後の問題は(おそらく)できなかったと思う。これは通常の UNIX コマン ドの組合せだけでは実現困難な処理の例である。 もちろんperl のプログラムを作成すれば簡単に実現できるのだが、このような単純な処 理を行うたびにいちいちperl プログラムを書くのは面倒だ。UNIX の既存のコマンドの 組合せでは難しいが、perl プログラムを作成するほど複雑ではない、そういう場合に役に 立つツールがここで紹介するawk である。 awk を使用するときの基本の構文を次に示す。 awk ‘パターン{ 処理 }’ 入力データファイル 上の構文でawk を実行すると、入力データファイルが一行づつ読み込まれ、もし その行が「パターン」の部分に記述された条件に合致していれば、その行に対して、「処 理」の部分に記述された処理を行う。 例えば、課題1 の第 15 問は、次のようにすれば解決だ。 1 Toritani 0.276 24 Hiyama 0.278 39 Yano 0.274 4 Sheets 0.290 53 Akahoshi 0.319 6 Kanemoto 0.325 7 Imaoka 0.281 9 Fujimoto 0.251 hanshin5.txt 1 144 7 24 117 8 39 137 19 4 135 19 53 143 1 6 144 39 7 144 29 9 117 1 hanshin6.txt 1 Toritani 0.276 144 7 4 Sheets 0.290 135 19 6 Kanemoto 0.325 144 39 7 Imaoka 0.281 144 29 9 Fujimoto 0.251 117 1 24 Hiyama 0.278 117 8 39 Yano 0.274 137 19 53 Akahoshi 0.319 143 1 hanshin4.txtawk ‘$1=="ATOM"&&$8<0{print}' 1UAO.pdb (1UAO.pdb の ATOM レコードのうち、原子の y 座標が負の数である行だけを表 示) $1=="ATOM"&&$8<0 が「パターン」である。これは、行の第 1 要素($1) が「A TOM 」 であり、かつ( && ) 、第 8 要素( $8 ) が負の数である( <0 ) という条件を表している。 上の例における、「処理」12は、print である。読んで字のごとく、「表示せよ」 という意味である。 パターンを省略した場合は、入力された全てのデータ行に対して「処理」を実行 する。例えば、次のコマンド文字列を実行してみよ。
awk ‘{print $1}’ 1UAO.pdb
また、{ 処理 }を省略した場合は、{print}と書いた場合と同じように動作する。よっ て、課題1 の第 15 問は、次のようにするのでも良い。
awk ‘$1=="ATOM"&&$8<0' 1UAO.pdb
(1UAO.pdb の ATOM レコードのうち、原子の y 座標が負の数である行だけを表 示) awk の使い方の詳しい内容は、実習時に別に配布するプリントを見よ。また、次 に挙げるのは、関連するURL である。 GNUawk の日本語マニュアル http://www.kt.rim.or.jp/%7Ekbk/gawk/gawk_toc.html awk の便利な一行野郎 http://www.kt.rim.or.jp/%7Ekbk/gawk/gawk_7.html#SEC45 12 awk では、この「処理」の部分のことを、「アクション」と呼ぶことが多い。