8
6

More than 5 years have passed since last update.

bashでTSV(タブ区切り)のデータを配列に入れる

Last updated at Posted at 2015-06-18

要件

TSV(タブ区切り)データを1行分持ってきて、各データを配列に入れたくなりました。

  • なるべく速く
  • 空データは空データとして格納する
  • 特殊文字(タブ以外)を許容する

結論

各データをシングルクォーテーションで括って配列に代入します。
TSVデータ行が変数STRに入っているとして

$ eval ARRAY=("$(sed -e "s/'/'\\\\''/g" -e "s/\t/'\t'/g" -e "s/^/'/" -e "s/$/'/" <<< "$STR")")

原理

evalについては以前の投稿 bash で ls 結果を配列に入れる - Qiita と同じです。
今回は、上記記事でls--quoting-style=shell-alwaysがやってくれていたことをsedでやりました。

sedでやっていること

例を示しながら書いてみます。
タブ部分はわかりやすいように<TAB>と書いています。

sed前:aaa<TAB>b b<TAB><TAB>dd'dd

sedでは以下の処理を行っています
1. シングルクォーテーションをエスケープ(''\'')。
aaa<TAB>b b<TAB><TAB>dd'\''dd
2. 先頭と末尾にシングルクォーテーションを配置。
'aaa<TAB>b b<TAB><TAB>dd'\''dd'
3. タブの前後にシングルクォーテーションを配置。
'aaa'<TAB>'b b'<TAB>''<TAB>'dd'\''dd'

sed後:'aaa'<TAB>'b b'<TAB>''<TAB>'dd'\''dd'

お試し

タブ区切りの文字列を用意します。

$ # テストデータ作成
$ STR=$(echo -e "\tbbb\tc c\t\te'e'e\t")
$ # 確認
$ echo "\"$STR\""
"       bbb     c c             e'e'e   "

配列に代入します。

$ # 配列に代入
$ eval ARRAY=("$(sed -e "s/'/'\\\\''/g" -e "s/\t/'\t'/g" -e "s/^/'/" -e "s/$/'/" <<< "$STR")")

結果を確認します。

$ # 配列の中身を確認
$ for VAL in "${ARRAY[@]}"; do echo "$VAL"; done

bbb
c c

e'e'e

$ # ↑最後の空文字も入っている

空のデータもちゃんと入りました。

発展:複数行

TSVファイル(複数行)の各行について処理したい場合は

while read -r LINE; do
    eval ARRAY=("$LINE")
    # 各行についての処理をここに書く
done < <(sed -e "s/'/'\\\\''/g" -e "s/\t/'\t'/g" -e "s/^/'/" -e "s/$/'/" "$FILE")

sedの実行が1度で済むのでこれが速そう。

発展:TSV以外

区切り文字の判別はsedの-e "s/\t/'\t'/g"が要になっている。
カンマ区切りのファイルを入力としたい場合はここを-e "s/,/'\t'/g"とすれば良い。

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6