【Shell】パイプを使ったループで連想配列に値を設定する

■ はじめに

https://dk521123.hatenablog.com/entry/2021/08/13/120956

にあるように、CSVの値を連想配列に詰めて、
マップを作成しようとしたけど、失敗したので、
その解決策について、記しておく。

目次

【1】トラブル
【2】原因
【3】解決案
 解決案1:shoptコマンドのlastpipeオプション
 解決案2:setコマンド

【1】トラブル

https://dk521123.hatenablog.com/entry/2021/08/13/120956

にあるように、CSVの値を連想配列に詰めて、
マップを作成しようとしたけど、空になってしまう。

ダメだった例

#!/bin/bash

declare -A dict;

sed 1d "sample_csv.csv" | while IFS=, read -r id db_name table_name; do
  dict["${id}"]="${db_name}.${table_name}"
done

# 値が表示されなかった
for key in ${!dict[@]};
do
  # キーを取得
  echo $key
   # 値を取得
  echo ${dict[$key]}
done

sample_csv.csv

id,db_name,table_name
1,db1,sample_table1_1
2,db1,sample_table1_2
3,db2,sample_table2_1

【2】原因

* パイプラインで読み込んでいるから

Bash shell, associative array empty after piping
https://superuser.com/questions/970036/bash-shell-associative-array-empty-after-piping

【3】解決案

解決案1:shoptコマンドのlastpipeオプション

https://stackoverflow.com/questions/19570413/how-to-pipe-input-to-a-bash-while-loop-and-preserve-variables-after-loop-ends

を参考に
「shopt -s lastpipe」を追加すると、意図した動作になる。

shopt コマンドの 詳細は、以下の関連記事を参照のこと。

https://dk521123.hatenablog.com/entry/2021/09/12/000000

OKだった例1

#!/bin/bash

# ★追加(lastpipe有効化)
shopt -s lastpipe

declare -A dict
sed 1d "sample_csv.csv" | while IFS=, read -r id db_name table_name; do
  dict["$id"]="$db_name.$table_name"
done

# ★元に戻す
shopt -u lastpipe

# 値が表示されなかった
for key in ${!dict[@]};
do
  # キーを取得
  echo $key
   # 値を取得
  echo ${dict[$key]}
done

解決案2:setコマンド

以下のサイトを参考になった。感謝。。。

https://crieit.net/posts/6417df54e9cc7b5492fe9b8d2af9e43e

* setコマンドに関する詳細は、以下の関連記事を参照のこと。

https://dk521123.hatenablog.com/entry/2021/09/14/000000
OKだった例2

#!/bin/bash

declare -A dict;

while IFS=, read -r id db_name table_name; do
  # ★
  set -- ${id} ${db_name} ${table_name}

  dict["${id}"]="${db_name}.${table_name}"
done <<< `sed 1d 'sample_csv.csv'`

# 値が表示されなかった
for key in ${!dict[@]};
do
  # キーを取得
  echo $key
   # 値を取得
  echo ${dict[$key]}
done

関連記事

シェル ~入門編~
https://dk521123.hatenablog.com/entry/2014/10/23/005406
シェル ~ 基本編 / 配列 ~
https://dk521123.hatenablog.com/entry/2021/08/11/000000
シェル ~ 基本編・構文全般 ~
https://dk521123.hatenablog.com/entry/2015/02/20/001600
シェル ~ 基本編・条件分岐 if / case ~
https://dk521123.hatenablog.com/entry/2015/05/01/000043
シェル ~ 基本編・ループ while / for etc ~
https://dk521123.hatenablog.com/entry/2021/08/09/000000
シェル ~ 基本編・関数 ~
https://dk521123.hatenablog.com/entry/2015/03/17/233124
シェル ~ 基本編・引数あれこれ ~
https://dk521123.hatenablog.com/entry/2021/07/11/000421
シェルで部分一致(前方一致・後方一致)
https://dk521123.hatenablog.com/entry/2020/09/01/000000
shoptコマンド
https://dk521123.hatenablog.com/entry/2021/09/12/000000
setコマンド
https://dk521123.hatenablog.com/entry/2021/09/14/000000
リダイレクト・パイプライン
https://dk521123.hatenablog.com/entry/2021/09/13/000000