kuroの覚え書き

96の個人的覚え書き

2つのファイルを比較して、一方に含まれる文字列を他方から抽出

a.txt

AT1G01000:10
AT1G01000:15
AT1G01000:20
AT1G01000:25
AT1G01001:10
AT1G01001:15
AT1G01001:20
AT1G01001:25
AT1G01002:10
AT1G01002:15
AT1G01002:20
AT1G01002:25
AT1G01003:10
AT1G01003:15
AT1G01003:20
AT1G01003:25
AT1G01004:10
AT1G01004:15
AT1G01004:20
AT1G01004:25
AT1G01004:30
AT1G01004:35
AT1G01005:10
AT1G01005:15
AT1G01005:20
AT1G01005:25
AT1G01005:30
AT1G01005:35
AT1G01006:10
AT1G01006:15
AT1G01006:20
AT1G01006:25
AT1G01006:30
AT1G01006:35
AT1G01006:40
AT1G01006:45
AT1G01006:50
AT1G01007:10
AT1G01007:15
AT1G01007:20
AT1G01007:25
AT1G01007:30
AT1G01007:35
AT1G01007:40
AT1G01008:10
AT1G01008:15
AT1G01008:20
AT1G01008:25
AT1G01008:30
AT1G01008:35
AT1G01008:40
AT1G01009:10
AT1G01009:15
AT1G01009:20
AT1G01009:25
AT1G01009:30
AT1G01010:10
AT1G01010:15
AT1G01010:20
AT1G01010:25
AT1G01010:30
AT1G01010:35
AT1G01010:40
AT1G01011:10
AT1G01011:15
AT1G01011:20
AT1G01011:25
AT1G01011:30
AT1G01011:35
AT1G01011:40
AT1G01012:10
AT1G01012:15
AT1G01012:20
AT1G01012:25
AT1G01013:10
AT1G01013:15
AT1G01013:20
AT1G01013:25
AT1G01014:10
AT1G01014:15
AT1G01014:20
AT1G01015:10
AT1G01015:15
AT1G01016:10
AT1G01016:15
AT1G01017:10
AT1G01017:15
AT1G01018:10
AT1G01018:15
AT1G01019:10
AT1G01019:15
AT1G01020:10
AT1G01020:15
AT1G01021:10
AT1G01021:15
AT1G01022:10
AT1G01022:15
AT1G01023:10
AT1G01023:15
AT1G01023:20

こんなファイルから
b.txt

AT1G01001
AT1G01002
AT1G01003
AT1G01004
AT1G01007
AT1G01008
AT1G01009
AT1G01011
AT1G01015
AT1G01016
AT1G01017
AT1G01018
AT1G01021
AT1G01022
AT1G01023

こんなファイルに含まれる文字列を含む行のみを取り出すにはどうしたらいいかな。

$ cat a.txt | sort | uniq -w 9 -d > a1.txt

こうするとa.txtのATxGxxxxxが共通する行の先頭の1行ずつが抽出される。

AT1G01000:10
AT1G01001:10
AT1G01002:10
AT1G01003:10
AT1G01004:10
AT1G01005:10
AT1G01006:10
AT1G01007:10
AT1G01008:10
AT1G01009:10
AT1G01010:10
AT1G01011:10
AT1G01012:10
AT1G01013:10
AT1G01014:10
AT1G01015:10
AT1G01016:10
AT1G01017:10
AT1G01018:10
AT1G01019:10
AT1G01020:10
AT1G01021:10
AT1G01022:10
AT1G01023:10

で、

$ cat a1.txt b.txt | sort -r | uniq -w9 -d > b1.txt

とするとb.txtと一致する文字列をふくむ行だけ取り出せる。
次に

$ cat a.txt a1.txt | sort | uniq -u > a2.txt

これでa1.txtに取り出した行はもとのa.txtから取り除かれる。
ここまでのサイクルを繰り返してやるとa.txtから順番に該当行が取り出されていって最後にはATxGxxxxxが違う行が1行ずつ残るので

$ cat a2.txt b.txt | sort -r | uniq -w 9 -d > bn.txt

これで全部抽出完了。
できたb1.txtからbn.txtまでをcatで繋いでsortしてやればめでたく完成。サイクルを何回回せばよいかは

$ cat a.txt | sort | uniq -w9 -c | sort -r | cut -d ' ' -f 7 | sed -n 1P

これで取得。(うそ、これではだめ)


これらをスクリプトに組み立てて一気に実行

#!/bin/sh
a='./3snp_list.txt'
b='./2exp_list.txt'
# RAM diskを作成するとき
echo "prepare 4G RAM disk"
NUMSCT=8192000
ramdev=`hdid -nomount ram://$NUMSCT`
diskutil partitionDisk $ramdev 1 HFS+ RAMdisk 4G

cat $a | sort > /Volumes/RAMdisk/a1
cat $b | sort > /Volumes/RAMdisk/b1
touch /Volumes/RAMdisk/b0
#同じgeneに最大何個のsnpが含まれているか
# cat a1 | uniq -w 9 -c | sort -r | sed -n 1P | awk '{sub("AT.*$", ""); print $0;}'> c
# c1=$(($(printf '%s' $(cat c))-1))
c1=$(($(cat /Volumes/RAMdisk/a1 | uniq -w 9 -c | sort -r | sed -n 1P | awk '{sub("AT.*$", ""); print $0;}')-1))
for cnt in `seq 1 $c1`
do
  #複数snpを含むgeneから一つずつsnpを抽出
  cat /Volumes/RAMdisk/a1 | sort | uniq -w 9 -d > /Volumes/RAMdisk/a2
  #比較するgene_listと照合して、合致するものを回収
  cat /Volumes/RAMdisk/a2 /Volumes/RAMdisk/b1 | sort -r | uniq -w9 -d > /Volumes/RAMdisk/b2
  cat /Volumes/RAMdisk/b0 /Volumes/RAMdisk/b2 > /Volumes/RAMdisk/b3
  mv /Volumes/RAMdisk/b3 /Volumes/RAMdisk/b0
  #a1からa2の行を除く
  cat /Volumes/RAMdisk/a1 /Volumes/RAMdisk/a2 | sort | uniq -u > /Volumes/RAMdisk/a3
  mv /Volumes/RAMdisk/a3 /Volumes/RAMdisk/a1
  echo $cnt
done
cat /Volumes/RAMdisk/a1 /Volumes/RAMdisk/b1 | sort -r | uniq -w9 -d > /Volumes/RAMdisk/b2
cat /Volumes/RAMdisk/b0 /Volumes/RAMdisk/b2 | sort > output.txt

RAMdiskとかちょっと姑息なことしてますが。