# 【新】用 bash 寫個由學名找物種資訊小功能
###### tags: `ubuntu` `學習筆記` `bash`
因為 [臺灣物種名錄](https://taicol.tw/) 網站搬家 + 大改版,原本的物種名錄資料格式也有很大的變動,例如名錄檔案分為「學名」與「物種」兩個檔案,前者記錄了更多的資訊如種下階層(subsp., var., fo.)、原始發表文獻、地位等等。對於整理調查資料來說,應該使用物種名錄檔案即可;但因為學名名錄檔才有紀錄是否為接受名(`usage_status`),所以我們也只好使用這個檔案來製作本機端的資料庫。如果新版網站延續之前 taibnet 的慣例,那名錄資料會每月更新一次,可以定期下載來更新本地端的比對用物種資料庫。
首先下載檔案:
```bash!
wget https://taicol.tw/static/upload/TaiCOL_name_20250630.zip
unzip TaiCOL_name_20230818.zip
```
查看每一行的名稱,共有 49 行,可以使用 `awk` 指令查看:
```bash!
awk -F, 'NR==1 {for (i=1; i<=NF; i++) {printf("$%d %s\n", i, $i)}}' TaiCOL_name_20230818.csv
$1 name_id
$2 nomenclature_name
$3 rank
$4 simple_name
$5 name_author
$6 formatted_name
$7 latin_genus
$8 latin_s1
$9 s2_rank
$10 latin_s2
$11 s3_rank
$12 latin_s3
$13 original_name_id
$14 is_hybrid
$15 hybrid_parent
$16 protologue
$17 type_name_id
$18 namecode
$19 created_at
$20 updated_at
$21 taxon_id
$22 usage_status
$23 is_in_taiwan
$24 common_name_c
$25 alternative_name_c
$26 is_endemic
$27 alien_type
$28 alien_status_note
$29 is_fossil
$30 is_terrestrial
$31 is_freshwater
$32 is_brackish
$33 is_marine
$34 cites
$35 iucn
$36 redlist
$37 protected
$38 sensitive
$39 kingdom
$40 kingdom_c
$41 phylum
$42 phylum_c
$43 class
$44 class_c
$45 order
$46 order_c
$47 family
$48 family_c
$49 genus
$50 genus_c
```
可以拿來篩選的欄位有第 3 欄 `rank`(分類階層,34 為物種,35、37、38、39、40、42 分別對應到不同的種下階層)與第 22 欄 `usage_status`(是否為接受名)。
因為現在 TaiCOL 僅提供 csv 格式的名錄,其中部分欄位若有多個值,會以雙引號框起來,裡面再以逗號分隔(例如 "節節草, 臺灣木賊, 筆管草, 台灣木賊")。這會造成資料處裡過程中很大的困擾,必須要先處理。
把那些帶有雙引號欄位中的分隔符號改為分號後,我們就可以在 awk 中依序篩選出接受名與需要的分類階層:
```bash=
sed -e 's/,\"/,/g' -e 's/\",/,/g' -e 's/, /;/g' TaiCOL_name_20250630.csv|\
awk -F, -v OFS="\t" '$22 == "usage_status" || $22 == "accepted" {print $3, $4, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $50, $4, $6, $5, $23, $24, $25, $26, $27, $34, $35, $36, $37, $38, $21}' > acc.TaiCOL_name_20250630.tsv
#如果用數字篩選無效的話,改為:awk -F'\t' '$1 == "Species" || $1 == "Subspecies" || $1 == "Variety" || $1 == "Form" || $1 == "Subvariety"\
awk -F'\t' '$1 == "34" || $1 == "35" || $1 == "37" || $1 == "38" || $1 == "39" || $1 == "40" || $1 == "42"\
{printf "sciname[%s]=\"%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\thttps://taicol.tw/taxon/%s\"\n",\
$2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28}' acc.TaiCOL_name_20230818.tsv > hash.acc.TaiCOL_name_20230818
#如果不想篩選階層
awk -F'\t' '{printf "sciname[%s]=\"%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\thttps://taicol.tw/taxon/%s\"\n",\
$2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24}' acc.TaiCOL_name_20230325.tsv > hash.acc.TaiCOL_name_20230325
```
可以注意到,印出的格式化字串中,已經把 associative table 的格式編排好了,所以就可以依照[用 bash 寫個由學名找物種資訊小功能](/5DfryrfqQGyrCTxykEMdzw)中的方法來加上開頭的宣告與最後的迴圈,就完成對應新版物種名錄的查找功能了。
```bash
cat $1|\
while read -r line; do
echo -e "$line\t${sciname[$line]}"
done
```
之後發現 word 有個小功能,可以把 _被底線包圍的文字_ 自動轉為 *斜體*,對我們的這個物種名錄對應功能來說,應該好好利用。
原本表單中的欄位就有 `formatted_name` 一項,使用 html 語法來設定學名的格式,所以我們只要把 `<i>` 與 `</i>` 替換為底線即可:
```bash
sed -i 's/<\/\?i>/_/g' queryTaiCOL_name_20230325.sh
```
測試結果:

使用這個小工具,就可以快速比對出調查物種的高階分類群與其他資訊,甚至連學名格式都設定好了。
2024.01.10 更新:
因為 TaiCOL 的學名名錄表格內容順序又變更了,附上最新的處理過程:
```bash=
wget https://taicol.tw/static/upload/TaiCOL_name_20240104.zip
unzip TaiCOL_name_20240104.zip
awk 'BEGIN{FS=OFS="\""} {for (i=1; i<=NF; i+=2) gsub(/,/, "|", $i); print}' TaiCOL_name_20240104.csv|\
sed 's/\"//g'|\
awk -F"|" -v OFS="\t" '$22 == "accepted"{print $3, $4, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48, $49, $4, $6, $5, $24, $25, $23, $26, $27, $33, $34, $35, $36, $37, $21}' > acc.TaiCOL_name_20240104.tsv
awk -F'\t' '$1 == "34" || $1 == "35" || $1 == "37" || $1 == "38" || $1 == "39" || $1 == "40" || $1 == "42"\
{printf "sciname[%s]=\"%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\thttps://taicol.tw/taxon/%s\"\n",\
$2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28}' acc.TaiCOL_name_20240104.tsv > hash.acc.TaiCOL_name_20240104
```
<span style="font-size:30px">🐕🦺</span>
---
TaiCOL 名錄裡 `rank` 的數字與種/種下階層對照:
|數字|階層|remark|
|-|-|-|
|34|Species|種|
|35|Subspecies|亞種|
|37|Variety|變種,常見於植物|
|38|Subvariety|亞變種|
|39|nothovar.|栽培雜交變種|
|40|Form|型,常見於植物|
|42|Forma specialis(f.sp.)|寄生專化型|
之後從 TaiCOL 獲得了 `rank_map` 如下可供參考:
<table>
<tr>
<td>1: 'Domain'</td>
<td>2: 'Superkingdom'</td>
<td>3: 'Kingdom'</td>
<td>4: 'Subkingdom'</td>
</tr>
<tr>
<td>5: 'Infrakingdom'</td>
<td>6: 'Superdivision'</td>
<td>7: 'Division'</td>
<td>8: 'Subdivision'</td>
</tr>
<tr>
<td>9: 'Infradivision'</td>
<td>10: 'Parvdivision'</td>
<td>11: 'Superphylum'</td>
<td>12: 'Phylum'</td>
</tr>
<tr>
<td>13: 'Subphylum'</td>
<td>14: 'Infraphylum'</td>
<td>15: 'Microphylum'</td>
<td>16: 'Parvphylum'</td>
</tr>
<tr>
<td>17: 'Superclass'</td>
<td>18: 'Class'</td>
<td>19: 'Subclass'</td>
<td>20: 'Infraclass'</td>
</tr>
<tr>
<td>21: 'Superorder'</td>
<td>22: 'Order'</td>
<td>23: 'Suborder'</td>
<td>24: 'Infraorder'</td>
</tr>
<tr>
<td>25: 'Superfamily'</td>
<td>26: 'Family'</td>
<td>27: 'Subfamily'</td>
<td>28: 'Tribe'</td>
</tr>
<tr>
<td>29: 'Subtribe'</td>
<td>30: 'Genus'</td>
<td>31: 'Subgenus'</td>
<td>32: 'Section'</td>
</tr>
<tr>
<td>33: 'Subsection'</td>
<td>34: 'Species'</td>
<td>35: 'Subspecies'</td>
<td>36: 'Nothosubspecies'</td>
</tr>
<tr>
<td>37: 'Variety'</td>
<td>38: 'Subvariety'</td>
<td>39: 'Nothovariety'</td>
<td>40: 'Form'</td>
</tr>
<tr>
<td>41: 'Subform'</td>
<td>42: 'Special Form'</td>
<td>43: 'Race'</td>
<td>44: 'Stirp'</td>
</tr>
<tr>
<td>45: 'Morph'</td>
<td>46: 'Aberration'</td>
<td>47: 'Hybrid Formula'</td>
<td></td>
</tr>
</table>