Linux で利用できるシェルスクリプト(文字列・配列・構文などの取り扱い方)
bash
bash はシェルスクリプトの一種で、ほとんどの Linux においてデフォルトのシェルとして使われている。簡単な繰り返し処理はもちろんのこと、大量なデータを処理する際もシェルスクリプトを書いて計算機に投入する必要があるので、シェルスクリプトは Linux ユーザーにとってなくてはならない存在である。
bash の変数
bash の変数には文字列あるいは配列を代入することができる。数字を代入しても、基本的に文字列として扱われる。
seq=ACAGTTAGCTAGCTGATGCACTAGTC
echo ${seq}
## ACAGTTAGCTAGCTGATGCACTAGTC
n=10
m=20
x=${n}+${m}
echo ${x}
## 10+20
arr=("AAA" "CCC" "GGG" "TTT")
echo ${arr}
## AAA
echo ${arr[@]}
## AAA CCC GGG TTT
bash では関数を定義することも可能で、その際に function
を利用して定義する。
function sum {
let x=$1+$2
echo ${x}
}
sum 10 20
## 30
bash 文字列
#
を利用することで、文字列の長さを求めることができる。
dna="TAGCATGCAGTCTATTATCGGATCGATGCTGACTAGTCAGCT"
echo ${#dna}
## 42
文字列の切り出しは、開始位置と終了位置を指定して切り出す。
echo ${dna:0:5}
## TAGCA
文字列の置換はスラッシュを利用する。マッチしたパターンすべてに対して置換を行うときは、//
を利用し、マッチしたパターンの最初の 1 つだけに対して置換を行う場合は /
を利用する。
echo ${dna//T/U}
## UAGCAUGCAGUCUAUUAUCGGAUCGAUGCUGACUAGUCAGCU
echo ${DNA/T/U}
## UAGCATGCAGTCTATTATCGGATCGATGCTGACTAGTCAGCT
文字列の連結は 2 つの変数連続して書けば良い。他のプログラミング言語のように + や . などの連結演算子は存在しない。
exon1="ACCCATCAGCGCATCGTACGTAC"
exon2="ACGTGGCGTCATGATGCAGAAAA"
cds=${exon1}${exon2}
echo ${cds}
## ACCCATCAGCGCATCGTACGTACACGTGGCGTCATGATGCAGAAAA
配列の要素を連結して 1 つの文字列にする場合は、まず連結する際に区切り文字として利用される文字を IFS
で指定してから、[*]
で配列を展開して、新しい変数に代入すれば良い。
exons=( "AACTCAGCAT" "TTGCGTGAGCT" "ACACGCTACCA")
IFS=""
cds="${exons[*]}"
echo ${cds}
## AACTCAGCATTTGCGTGAGCTACACGCTACCA
1 つの文字列を区切り文字で分割して、配列にすることもできる。
allfeatures="CDS,mRNA,exon,exon,intron,ncRNA"
IFS=","
features=(${allfeatures})
echo ${features}
## CDS mRNA exon exon intron ncRNA
bash 配列
配列の作成
bash の配列を作るには、複数の要素を括弧で囲んで、変数に代入すれば良い。要素と要素の間はスペースで区切る。
arr=()
arr=("magnoliids" "monocots" "eudicots")
配列を作ってから、添え字を指定して要素の変更や追加を行うこともできる。
arr=()
brr=("mag" "mon" "eud")
arr[0]="NN_CC320"
echo ${arr[@]}
## NN_CC320
arr=("${brr[@]}" "NM_AC001" "NX_CB201")
echo ${arr[@]}
## mag mon eud NM_AC001 NX_CB201
arr[2]="NX_CB202"
echo ${arr[@]}
## mag mon NX_CB202 NM_AC001 NX_CB201
配列要素の取り出し
要素を取り出すときは、添え字を指定して取り出す方法の他に、開始位置と終了位置を指定して複数の要素を取り出すこともできる。
div=("FUN" "PLN" "PRT" "MAM" "HUM" "VRT")
echo ${div[0]}
## FUN
echo ${div[@]:2:2}
## PRT MAM
echo ${div[@]:2}
## PRT MAM HUM VRT
echo ${div[${#div[@]}-1]}
#VRT
配列中すべての要素を順番に取り出す場合は for
を利用する。次のように、添え字を介して要素を取り出す方法と、要素自体を取り出す方法がある
div=("FUN" "PLN" "PRT" "MAM" "HUM" "VRT")
for (( i = 0; i < ${#div[@]}; ++i ))
do
echo ${div[$i]}
done
for domain in ${div[@]}
do
echo ${domain}
done
配列要素の置換
bash では、配列の要素に対して一括に置換などを行うことができる。ファイル名から拡張子を削除したり、あるいは拡張子を変更したりする場合に便利。
filenames=("NC_01.1.fasta" "NC_02.1.fasta" "NC_03.2.fasta")
# fasta を fa に置換する
echo ${filenames[@]/fasta/fa}
## NC_01.1.fa NC_02.1.fa NC_03.2.fa
# .fasta を消す
echo ${filenames[@]/\.fasta/}
## NC_01.1 NC_02.1 NC_03.2
# 先頭から最初にマッチした位置まで取り除く
echo ${filenames[@]#*\.}
##1.fasta 1.fasta 2.fasta
# 先頭から最後にマッチした位置まで取り除く
echo ${filenames[@]##*\.}
## fasta fasta fasta
# 末尾から最初にマッチした位置まで取り除く
echo ${filenames[@]%\.*}
## NC_01.1 NC_02.1 NC_03.2
# 末尾から最後にマッチした位置まで取り除く
echo ${filenames[@]%%\.*}
## 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 の関数に戻り値がないので、戻り値利用する場合はあらかじめグローバル変数を 1 つ用意しておく必要がある。
y=""
function sum {
let x=$1+$2
y=${x}
}
sum 10 20
echo ${y}
## 30
bash 制御構文
if 構文
2 つの値を比較して真偽を判定してから、次の処理を行う if
構文は次のようにかける。bash の 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
構文は配列の要素を 1 つずつ繰り返しながらとる出すループ構文である。
for i in 1 2 3 4 5
do
echo $i #1 2 3 4 5
done
for i in {1..5}
do
echo $i #1 2 3 4 5
done
for i in {1..10..2}
do
echo $i #1 3 5 7 9
done
for (( i=0; i<=5; i++ ))
do
echo $i #0 1 2 3 4 5
done
for i in {1..10}
do
if [ $i -gt 3 ]
then
echo $i #4
break
fi
done
while 構文
while
構文は、与えられた条件が真である限り繰り返すループ構文である。
declare -i i=0
while [ $i -lt 5 ]
do
echo $i #0 1 2 3 4
let i+=1
done
ほぼ同じような機能を有する until
構文もある。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
サンプル
拡張子を変換
現在のディレクトリにある拡張子「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
パイプで変数を利用
シェルスクリプトでパイプを利用するとき、パイプ左側の内容を変数に代入し、パイプ右側で利用することができる。while read
を利用する。
echo "SRR000001 SRR000002 SRR000003" | while read line
do
IFS=" "
fqs=(${line})
for f in ${fqs[@]}
do
echo ${f}.fq
done
done
## SRR000001.fq
## SRR000002.fq
## SRR000003.fq
.bashrc と .bash_profile
bash の環境変数の設定やエイリアスの定義などは .bashrc あるいは .bash_profile に書く。.bashrc に書いた定義などは bash スクリプトを実行するとき、実行直前に読み込まれる。一方で、.bash_profile はログインするときにしか実行されない。
References
- UNIX for Bioinformatics https://aabbdd.jp/unix4bi/