bash

bash はシェルスクリプトの一種で、ほとんどの Linux においてデフォルトのシェルとして使われている。簡単な繰り返し処理はもちろんのこと、大量なデータを処理する際もシェルスクリプトを書いて計算機に投入する必要がある。

bash 変数型と変数の宣言

bash の変数は、宣言を必要としない。文字列型、整数型や配列型などがある。

# 文字列(そのまま代入します)
seq=ACAGTTAGCTAGCTGATGCACTAGTC
echo ${seq}
## ACAGTTAGCTAGCTGATGCACTAGTC


# 文字列(整数)
n=10
m=20
#n, m は文字列型で保存されているため、四則計算を行うときは、let を援用
let x=${n}+${m}
echo ${x}
30


# 配列
arr=("AAA" "CCC" "GGG" "TTT")
echo ${arr}
## AAA
echo ${arr[@]}
## AAA CCC GGG TTT


# 関数
function sum {
  let x=$1+$2
  echo ${x}
}
sum 10 20
## 30

bash 文字列

bash で文字列の切り出し、置換や連結を行う例。

#文字列の長さ
DNA="TAGCATGCAGTCTATTATCGGATCGATGCTGACTAGTCAGCT"
echo ${#DNA}
## 42

 
#文字列切り出し
echo ${DNA:0:5}
## TAGCA

 
#文字列置換 //は全部置換、/は最初にマッチしたものだけを置換
echo ${DNA//T/U}
## UAGCAUGCAGUCUAUUAUCGGAUCGAUGCUGACUAGUCAGCU

echo ${DNA/T/U}
## UAGCATGCAGTCTATTATCGGATCGATGCTGACTAGTCAGCT
 

#文字列連結
EXON1="ACCCATCAGCGCATCGTACGTAC"
EXON2="ACGTGGCGTCATGATGCAGAAAA"
CDS=${EXON1}${EXON2}
echo ${CDS}
## ACCCATCAGCGCATCGTACGTACACGTGGCGTCATGATGCAGAAAA

 
#配列連結 IFSで区切り文字を設定する
EXONS=( "AACTCAGCAT" "TTGCGTGAGCT" "ACACGCTACCA")
IFS=""
CDS="${EXONS[*]}"
echo ${CDS}
## AACTCAGCATTTGCGTGAGCTACACGCTACCA

 
#文字列分割 IFSで区切り文字を設定する
ALLFEATURES="CDS,mRNA,exon,exon,intron,ncRNA"
IFS=","
FEATURES=(${ALLFEATURES})
echo ${ALLFEATURES}
## CDS mRNA exon exon intron ncRNA

bash 配列

bash の配列の作成方法と for 文を利用して全要素を取り出す方法の例。

#配列の宣言
APG=()
APG=("magnoliids" "monocots" "eudicots")
 
 
#配列要素の追加
ACCESSION=()
ACCESSION[0]="NN_CC320"
ACCESSION=("${ACCESSION}[@]" "NM_AC001" "NX_CB201")
ACCESSION[2]="NX_CB202"
 
 
#配列要素の取り出し
DIVISION=("FUN" "PLN" "PRT" "MAM" "HUM" "VRT")
echo ${DIVISION[0]}     # FUN
echo ${DIVISION[@]:2:2} # PRT MAM
echo ${DIVISION[@]:2}   # PRT MAM HUM VRT
echo ${DIVISION[${#DIVISION[@]}-1]} #VRT

 
#for文利用1
for (( i = 0; i < ${#DIVISION[@]}; ++i ))
do
    echo ${DIVISION[$i]}
done
 

#for文利用2
for domain in ${DIVISION[@]}
do
    echo ${domain}
done
 
 
#配列要素の置換編集
FASTA=("NC_01.1.fasta" "NC_02.1.fasta" "NC_03.2.fasta")
 

#fastaをfaに置換する
echo ${FASTA[@]/fasta/fa} 
## NC_01.1.fa NC_02.1.fa NC_03.2.fa

echo ${FASTA[@]/\.fasta/}   
## NC_01.1 NC_02.1 NC_03.2

 
#先頭から最初にマッチした位置まで取り除く
echo ${FASTA[@]#*\.} 
##1.fasta 1.fasta 2.fasta

 
#先頭から最後にマッチした位置まで取り除く
echo ${FASTA[@]##*\.} 
## fasta fasta fasta

 
#末尾から最初にマッチした位置まで取り除く
echo ${FASTA[@]%\.*} 
## NC_01.1 NC_02.1 NC_03.2
 

#末尾から最後にマッチした位置まで取り除く
echo ${FASTA[@]%%\.*} 
## NC_01 NC_02 NC_03

bash 関数

bash で関数を定義するときは function を利用する。関数の引数は $1$2、…のように参照する。


# 入力された二つの引数の和を出力する関数
function sum {
  let x=$1+$2
  echo ${x}
}

# 「関数名 第1引数 第2引数」のように並べて呼び出す
sum 10 20
## 30

bash 制御構文

bash で利用する制御構文。条件判断を行う if 文、繰り返し処理を行う for 文や while 文などがある。

#IF文
n=10
m=20
if [ ${n} -eq ${m} ]
    then
        echo "n = m"
elif [ ${n} -lt ${m} ]
    then
        echo "n < m"
else
        echo "n > m"
fi
 
 
#FOR文サンプル
for i in 1 2 3 4 5
do
    echo $i    #1 2 3 4 5
done
 

#FOR文サンプル
for i in {1..5}
do
    echo $i    #1 2 3 4 5
done

 
#FOR文サンプル
for i in {1..10..2}
do
    echo $i    #1 3 5 7 9
done

 
#FOR文サンプル
for (( i=0; i<=5; i++ ))
do
    echo $i    #0 1 2 3 4 5
done

 
#FOR文サンプル
for i in {1..10}
do
    if [ $i -gt 3 ]
        then
            echo $i  #4
            break
    fi
done


#WHILE文サンプル
declare -i i=0
while [ $i -lt 5 ]
do
    echo $i     #0 1 2 3 4
    let i+=1
done


#UNTIL文サンプル
declare -i i=9
until [ $i -lt 5 ]
do
    echo $i     #9 8 7 6 5
    let i-=1
done

特殊変数と演算子

bash で利用される特殊変数と演算子。

# 特殊変数
$0      #シェルスクリプト名
$1      #第1引数
$2      #第2引数
$#      #引数の個数
$@      #すべての引数を展開 "$1" "$2" ...
$*      #すべての引数を展開 "$1 $2 ..."
$?      #直前に実行したコマンドの終了ステータス
$!      #直前に実行したコマンドのPID
$$      #シェルスクリプトのPID

# 算術演算子
N + M
N - M
N * M
N / M
N % M   #剰余
 
# 論理演算子
N & M   #AND
N | M   #OR
N = M   #==
N > M   #>
N >= M  #>=
N < M   #<
N <= M  #<=
N != M  #!=
 
# 比較演算子
N -eq M
N -lt M
N -gt M
N -le M
N -ge M

予約語

PIPESTATUS$? には直前の操作の終了ステータス(正常:0、異常:1)しか保存されない。例えば、パイプを利用して複数のコマンドを実行した場合などは最後の終了ステータスが $? に保存される。これに対して、すべてのコマンドの終了ステータスが配列として PIPESTATUS に保存される。
cat /etc/passwd | grep root | sed 's/aaa/b//g'
echo ${PIPESTATUS[@]}
## 0 141 1

サンプル

拡張子を変換

現在のディレクトリにある拡張子「fasta」で終わるファイルを「fa」に変更する例。

for i in `ls *.fasta`
do
  mv ${i} ${i%.fasta}.fa
done

ファイル名の一括変換

ファイル名に「AAA」が含んでいれば、それを「BBB」に変更する例。

for i in `ls *AAA*`
do
  mv ${i} `echo ${i} | sed 's/AAA/BBB/g'`
done

ファイルを一つにまとめる

複数の fastq ファイルを一つのファイルにまとめる例。

for i in `*.fastq`
do
  cat ${i} >> all.fastq
done

連番の SRA ファイルをダウンロードして展開する

連番のシーケンサーデータをダウンロードして、展開する例。base_url については事前に調べておく必要ある。

# SRA Accession number
sra_list=({1169893..1169895})
# NCBI SRA toolkit へのパス
sratoolkit=/work/tools/sratoolkit.2.3.2-5/bin
# ダウンロード用のベース URL
base_url=ftp://ftp-trace.ncbi.nlm.nih.gov/sra/sra-instant/reads/ByStudy/sra/SRP/SRP037/SRP037986

# ダウンロード
for sra_id in ${sra_list[@]}
do
    wget ${base_url}/SRR${sra_id}/SRR${sra_id}.sra
    sleep 10m
done

# SRA から FASTQ へ変換(展開)
for sra_id in ${sra_list[@]}
do
    ${sratoolkit}/fastq-dump -O ${path_fastq} ${path_sra}/SRR${sra_id}.sra
done

パイプで変数を利用

シェルスクリプトでパイプを利用するとき、パイプ左側の内容を変数に代入し、パイプ右側で利用することができる。while read を利用する。

echo "SRR000001 SRR000002 SRR000003" | while read line
do
    echo ${line}.fastq
done
## SRR000001 SRR000002 SRR000003.fastq

各 SRR 番号を個々に出力したい場合は以下のようにする。awk でスペースを区切り文字として、1 行を分割し、パイプの右側の while read に渡す。

echo "SRR000001 SRR000002 SRR000003" | awk 'BEGIN{FS=" "}{
    for (i = 1; i <= NF; i++) {
        print $i
    }
}' | while read sra
do
    echo ${sra}.fastq
done
## SRR000001.fastq
## SRR000002.fastq
## SRR000003.fastq

.bashrc と .bash_profile

bash の環境変数の設定やエイリアスの定義などは .bashrc あるいは .bash_profile に書く。.bashrc に書いた定義などは bash スクリプトを実行するとき、実行直前に読み込まれる。一方で、.bash_profile はログインした時にしか実行されない。