※当サイトの記事には、広告・プロモーションが含まれます。

シェルスクリプトの疑似的な2次元連想配列のキーでソートした結果は保持されない問題

cafe-dc.com

買収が完了した後、BroadcomVMware への投資を約束しました。「Broadcom には、買収した事業に投資して持続可能な成長を推進してきた長い実績があります」 と、Broadcom の CEO である Hock Tan 氏は述べています。

Broadcom 買収完了の数日後にVMware がレイオフ実施 | Data Center Café

VMwareは、 Broadcomが690億ドルで同社の買収を発表した数日後に、多数の従業員を解雇することを発表しました。

Broadcom 買収完了の数日後にVMware がレイオフ実施 | Data Center Café

⇧ う~む、『Broadcom には、買収した事業に投資して持続可能な成長を推進してきた長い実績があります」』って言葉の信憑性が全くない行動をされると、過去の買収した事業で本当に実績があったのか疑わしく感じられてしまいますな...

で、

www.reddit.com

JavaのメジャーなフレームワークであるSpring Frameworkの開発で重要なポジションにおられた方も解雇されたようで、JavaでSpring Projectに関するライブラリを利用している界隈がザワついてますな。

他のフレームワークとか学習したくないから、Spring Projectは開発を維持していって欲しいけど...

シェルスクリプトの疑似的な2次元連想配列のキーでソートした結果は保持されない問題

前回、

ts0818.hatenablog.com

Linuxシェルスクリプトで、配列、または、連想配列を関数の引数として利用する方法が統一されていない、という話に触れていて、疑似的な2次元連想配列のソート結果は保持されないことが判明したので、備忘録として残しておきます。

正確には、ソートは可能、しかし、変数としてソート後の内容を保持できない、になります。

シェルスクリプトの仕様なのか分かりませんが、そういうことらしいです。

そもそも、

www.gnu.org

GNUが公開しているBashのドキュメントには、1次元の配列を提供するとしか記載が無いので、2次元以上の配列については与り知らぬ、ということなのかもしらんので、疑似的な2次元連想配列のソートについては、想定の範囲外ということなのかもね...

community.unix.com

www.nemotos.net

⇧ 上記サイト様を参考にさせていただきました。

■/home/ts0818/work/test_arr/test_arr.sh

#!/bin/bash

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  疑似的な2次元配列をソートした状態で出力
# ■    引数
# ■      param $1 出力ファイル(国の人口の連想配列)
# ■      param $2 国の人口の連想配列(疑似的2次元連想配列用)
# ■      param $3 ソート後用(国の人口の連想配列(疑似的2次元連想配列用))
# ■    戻り値
# ■      ソート後用(国の人口の連想配列(疑似的2次元連想配列用))
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
function print_sorted_associative_arr_by_key() {
  local _country_population="$1"
  declare -n ref_country_population_arr="$2"
  declare -n ref_sorted_associative_arr="$3"

  for idx in $(<<< ${!ref_country_population_arr[@]} tr ' ' '\n' | sort -t- -k1 -n);
  do 
    echo "$idx: ${ref_country_population_arr[$idx]}" | tee -a ${_country_population}
    ref_sorted_associative_arr["${idx}"]="${ref_country_population_arr[$idx]}"
  done
}


# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  出力
# ■    引数
# ■      param $1 出力ファイル(国の配列)
# ■      param $2 出力ファイル(国の人口の連想配列)
# ■      param $3 国の配列
# ■      param $4 国の人口の連想配列(疑似的2次元連想配列用)
# ■    戻り値
# ■      なし
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
function print_arr() {
  local _country="$1"
  local _country_population="$2"
  declare -n ref_country_arr="$3"
  declare -n ref_country_population_arr="$4"
  
  for element in ${ref_country_arr[@]};
  do
    echo "${element}" | tee -a ${_country}
  
  done

  for key in ${!ref_country_population_arr[@]};
  do
    # 疑似的二次元配列の内容を書き込む
    echo "${key}"'='"${ref_country_population_arr[${key}]}" | tee -a ${_country_population}
  done

}

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  疑似的な2次元連想配列を生成する
# ■    引数
# ■      param $1 国の人口の連想配列(疑似的2次元連想配列用)
# ■      param $2 国毎の人口の連想配列
# ■    戻り値
# ■      国の人口の連想配列(疑似的2次元連想配列用)
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

function generate_two_dimention_associative_arr() {
  declare -n ref_country_population_arr="$1"
  declare -n ref_country_population_all_arr="$2"
  local _idx_arr="$3"

  for key in ${!ref_country_population_arr[@]};
  do
    ref_country_population_all_arr[${_idx_arr}-${key}]="${ref_country_population_arr[${key}]}"
  done

}

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  実処理
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

LOG=test_arr.log

# 配列
declare -a country_arr=(
 "China"
 "India"
 "America"
 "Indonesia"
 "Pakistan"
 "Brazil"
 "Nigeria"
 "Bangladesh"
 "Russia"
 "Mexico"
 "Japan"
)

# 連想配列
#declare -A country_population_arr=(
# ["China"]=("1,425,894" "728,050" "697,843")
# ["India"]=("1,407,564" "726,503" "681,060")
# ["America"]=("336,998" "166,942" "170,056")
# ["Indonesia"]=("273,753" "137,852" "135,901")
# ["Pakistan"]=("231,402" "116,816" "114,586")
# ["Brazil"]=("214,326" "105,291" "109,035")
# ["Nigeria"]=("213,401" "107,827" "105,574")
# ["Bangladesh"]=("169,356" "83,998" "85,358")
# ["Russia"]=("145,103" "67,393" "77,710")
# ["Mexico"]=("126,705" "61,856" "64,849")
# ["Japan"]=("124,613" "60,568" "64,045")
#)


declare -A china_population_arr=(["China"]="1,425,894" ["Men"]="728,050" ["Women"]="697,843")
declare -A india_population_arr=(["India"]="1,407,564" ["Men"]="726,503" ["Women"]="681,060")
declare -A america_population_arr=(["America"]="336,998" ["Men"]="166,942" ["Women"]="170,056")
declare -A indonesia_population_arr=(["Indonesia"]="273,753" ["Men"]="137,852" ["Women"]="135,901")
declare -A pakistan_population_arr=(["Pakistan"]="231,402" ["Men"]="116,816" ["Women"]="114,586")
declare -A brazil_population_arr=(["Brazil"]="214,326" ["Men"]="105,291" ["Women"]="109,035")
declare -A nigeria_population_arr=(["Nigeria"]="213,401" ["Men"]="107,827" ["Women"]="105,574")
declare -A bangladesh_population_arr=(["Bangladesh"]="169,356" ["Men"]="83,998" ["Women"]="85,358")
declare -A russia_population_arr=(["Russia"]="145,103" ["Men"]="67,393" ["Women"]="77,710")
declare -A mexico_population_arr=(["Mexico"]="126,705" ["Men"]="61,856" ["Women"]="64,849")
declare -A japan_population_arr=(["Japan"]="124,613" ["Men"]="60,568" ["Women"]="64,045")

#declare -A country_population_arr=(
# [0]=$(declare -p china_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [1]=$(declare -p india_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [2]=$(declare -p america_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [3]=$(declare -p indonesia_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+"  '{ print  "(" $2 $3 $4 $5 }')
# [4]=$(declare -p pakistan_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+"  '{ print "(" $2 $3 $4 $5 }')
# [5]=$(declare -p brazil_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+"  '{ print "(" $2 $3 $4 $5 }')
# [6]=$(declare -p nigeria_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [7]=$(declare -p bangladesh_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [8]=$(declare -p russia_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [9]=$(declare -p mexico_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [10]=$(declare -p japan_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
#)

declare -A country_population_arr
#country_population_arr[0]=${!china_population_arr[@]}'='${china_population_arr[@]}
#country_population_arr[1]=${!india_population_arr[@]}'='${india_population_arr[@]}
#country_population_arr[2]=${!america_population_arr[@]}'='${america_population_arr[@]}
#country_population_arr[3]=${!indonesia_population_arr[@]}'='${indonesia_population_arr[@]}
#country_population_arr[4]=${!pakistan_population_arr[@]}'='${pakistan_population_arr[@]}
#country_population_arr[5]=${!brazil_population_arr[@]}'='${brazil_population_arr[@]}
#country_population_arr[6]=${!nigeria_population_arr[@]}'='${nigeria_population_arr[@]}
#country_population_arr[7]=${!bangladesh_population_arr[@]}'='${bangladesh_population_arr[@]}
#country_population_arr[8]=${!russia_population_arr[@]}'='${russia_population_arr[@]}
#country_population_arr[9]=${!mexico_population_arr[@]}'='${mexico_population_arr[@]}
#country_population_arr[10]=${!japan_population_arr[@]}'='${japan_population_arr[@]}

generate_two_dimention_associative_arr china_population_arr country_population_arr 0
generate_two_dimention_associative_arr india_population_arr country_population_arr 1
generate_two_dimention_associative_arr america_population_arr country_population_arr 2
generate_two_dimention_associative_arr indonesia_population_arr country_population_arr 3
generate_two_dimention_associative_arr pakistan_population_arr country_population_arr 4
generate_two_dimention_associative_arr brazil_population_arr country_population_arr 5
generate_two_dimention_associative_arr nigeria_population_arr country_population_arr 6
generate_two_dimention_associative_arr bangladesh_population_arr country_population_arr 7
generate_two_dimention_associative_arr russia_population_arr country_population_arr 8
generate_two_dimention_associative_arr mexico_population_arr country_population_arr 9
generate_two_dimention_associative_arr japan_population_arr country_population_arr 10

declare -p country_population_arr | tee -a ${LOG}

declare -A sorted_arr

#mapfile -d '' sorted_arr < <(printf '%s\0' "${!country_population_arr[@]}" | sort -z)
#declare -p sorted_arr | tee -a ${LOG}

print_sorted_associative_arr_by_key "${country_population}" country_population_arr sorted_arr
declare -p sorted_arr | tee -a ${LOG}

country=country.txt
country_population=country_population.txt

print_arr "${country}" "${country_population}" country_arr country_population_arr

    

⇧ ちなみに、疑似的な2次元連想配列のキーを、カンマ繋ぎではなくハイフン繋ぎに変更してます。カンマ繋ぎだとソートが上手くできなかったので...

で、実行すると、

⇧ ソートした内容は、変数に格納されると、また、ソート前のぐちゃぐちゃの状態に戻ってしまうと。

番号でのソートはできたものの、国名からの順番にというのができていないので、疑似的な2次元連想配列のキーの作成で、番号に枝番のような項番を付けるなど工夫して、番号と枝番でソートするようにするなどは必要そう。

良い案が浮かばないので、暫定対応として、列(カラム)に番号を振ったバージョンについても掲載。

■/home/ts0818/work/test_arr/test_arr.sh

#!/bin/bash

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  疑似的な2次元配列をソートした状態で出力
# ■    引数
# ■      param $1 出力ファイル(国の人口の連想配列)
# ■      param $2 国の人口の連想配列(疑似的2次元連想配列用)
# ■      param $3 ソート後用(国の人口の連想配列(疑似的2次元連想配列用))
# ■    戻り値
# ■      ソート後用(国の人口の連想配列(疑似的2次元連想配列用))
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
function print_sorted_associative_arr_by_key() {
  local _country_population="$1"
  declare -n ref_country_population_arr="$2"
  declare -n ref_sorted_associative_arr="$3"

  for idx in $(<<< ${!ref_country_population_arr[@]} tr ' ' '\n' | sort -t- -k1 -n);
  do 
    echo "$idx: ${ref_country_population_arr[$idx]}" | tee -a ${_country_population}
    ref_sorted_associative_arr["${idx}"]="${ref_country_population_arr[$idx]}"
  done
}


# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  出力
# ■    引数
# ■      param $1 出力ファイル(国の配列)
# ■      param $2 出力ファイル(国の人口の連想配列)
# ■      param $3 国の配列
# ■      param $4 国の人口の連想配列(疑似的2次元連想配列用)
# ■    戻り値
# ■      なし
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
function print_arr() {
  local _country="$1"
  local _country_population="$2"
  declare -n ref_country_arr="$3"
  declare -n ref_country_population_arr="$4"
  
  for element in ${ref_country_arr[@]};
  do
    echo "${element}" | tee -a ${_country}
  
  done

  for key in ${!ref_country_population_arr[@]};
  do  
    # 疑似的二次元配列の内容を書き込む
    echo "${key}"'='"${ref_country_population_arr[${key}]}" | tee -a ${_country_population}
  done

}

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  疑似的な2次元連想配列を生成する
# ■    引数
# ■      param $1 国の人口の連想配列(疑似的2次元連想配列用)
# ■      param $2 国毎の人口の連想配列
# ■    戻り値
# ■      国の人口の連想配列(疑似的2次元連想配列用)
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

function generate_two_dimention_associative_arr() {
  declare -n ref_country_population_arr="$1"
  declare -n ref_country_population_all_arr="$2"
  local _idx_arr="$3"

  for key in ${!ref_country_population_arr[@]};
  do
    ref_country_population_all_arr[${_idx_arr}-${key}]="${ref_country_population_arr[${key}]}"
  done

}

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■  実処理
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■

LOG=test_arr.log

# 配列
declare -a country_arr=(
 "China"
 "India"
 "America"
 "Indonesia"
 "Pakistan"
 "Brazil"
 "Nigeria"
 "Bangladesh"
 "Russia"
 "Mexico"
 "Japan"
)

# 連想配列
#declare -A country_population_arr=(
# ["China"]=("1,425,894" "728,050" "697,843")
# ["India"]=("1,407,564" "726,503" "681,060")
# ["America"]=("336,998" "166,942" "170,056")
# ["Indonesia"]=("273,753" "137,852" "135,901")
# ["Pakistan"]=("231,402" "116,816" "114,586")
# ["Brazil"]=("214,326" "105,291" "109,035")
# ["Nigeria"]=("213,401" "107,827" "105,574")
# ["Bangladesh"]=("169,356" "83,998" "85,358")
# ["Russia"]=("145,103" "67,393" "77,710")
# ["Mexico"]=("126,705" "61,856" "64,849")
# ["Japan"]=("124,613" "60,568" "64,045")
#)


declare -A china_population_arr=(["1.China"]="1,425,894" ["2.Men"]="728,050" ["3.Women"]="697,843")
declare -A india_population_arr=(["1.India"]="1,407,564" ["2.Men"]="726,503" ["3.Women"]="681,060")
declare -A america_population_arr=(["1.America"]="336,998" ["2.Men"]="166,942" ["3.Women"]="170,056")
declare -A indonesia_population_arr=(["1.Indonesia"]="273,753" ["2.Men"]="137,852" ["3.Women"]="135,901")
declare -A pakistan_population_arr=(["1.Pakistan"]="231,402" ["2.Men"]="116,816" ["3.Women"]="114,586")
declare -A brazil_population_arr=(["1.Brazil"]="214,326" ["2.Men"]="105,291" ["3.Women"]="109,035")
declare -A nigeria_population_arr=(["1.Nigeria"]="213,401" ["2.Men"]="107,827" ["3.Women"]="105,574")
declare -A bangladesh_population_arr=(["1.Bangladesh"]="169,356" ["2.Men"]="83,998" ["3.Women"]="85,358")
declare -A russia_population_arr=(["1.Russia"]="145,103" ["2.Men"]="67,393" ["3.Women"]="77,710")
declare -A mexico_population_arr=(["1.Mexico"]="126,705" ["2.Men"]="61,856" ["3.Women"]="64,849")
declare -A japan_population_arr=(["1.Japan"]="124,613" ["2.Men"]="60,568" ["3.Women"]="64,045")

#declare -A country_population_arr=(
# [0]=$(declare -p china_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [1]=$(declare -p india_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [2]=$(declare -p america_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [3]=$(declare -p indonesia_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+"  '{ print  "(" $2 $3 $4 $5 }')
# [4]=$(declare -p pakistan_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+"  '{ print "(" $2 $3 $4 $5 }')
# [5]=$(declare -p brazil_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+"  '{ print "(" $2 $3 $4 $5 }')
# [6]=$(declare -p nigeria_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [7]=$(declare -p bangladesh_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [8]=$(declare -p russia_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [9]=$(declare -p mexico_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
# [10]=$(declare -p japan_population_arr | cut -d ' ' -f 3- | awk -F"[=(]+" '{ print "(" $2 $3 $4 $5 }')
#)

declare -A country_population_arr
#country_population_arr[0]=${!china_population_arr[@]}'='${china_population_arr[@]}
#country_population_arr[1]=${!india_population_arr[@]}'='${india_population_arr[@]}
#country_population_arr[2]=${!america_population_arr[@]}'='${america_population_arr[@]}
#country_population_arr[3]=${!indonesia_population_arr[@]}'='${indonesia_population_arr[@]}
#country_population_arr[4]=${!pakistan_population_arr[@]}'='${pakistan_population_arr[@]}
#country_population_arr[5]=${!brazil_population_arr[@]}'='${brazil_population_arr[@]}
#country_population_arr[6]=${!nigeria_population_arr[@]}'='${nigeria_population_arr[@]}
#country_population_arr[7]=${!bangladesh_population_arr[@]}'='${bangladesh_population_arr[@]}
#country_population_arr[8]=${!russia_population_arr[@]}'='${russia_population_arr[@]}
#country_population_arr[9]=${!mexico_population_arr[@]}'='${mexico_population_arr[@]}
#country_population_arr[10]=${!japan_population_arr[@]}'='${japan_population_arr[@]}

generate_two_dimention_associative_arr china_population_arr country_population_arr 0
generate_two_dimention_associative_arr india_population_arr country_population_arr 1
generate_two_dimention_associative_arr america_population_arr country_population_arr 2
generate_two_dimention_associative_arr indonesia_population_arr country_population_arr 3
generate_two_dimention_associative_arr pakistan_population_arr country_population_arr 4
generate_two_dimention_associative_arr brazil_population_arr country_population_arr 5
generate_two_dimention_associative_arr nigeria_population_arr country_population_arr 6
generate_two_dimention_associative_arr bangladesh_population_arr country_population_arr 7
generate_two_dimention_associative_arr russia_population_arr country_population_arr 8
generate_two_dimention_associative_arr mexico_population_arr country_population_arr 9
generate_two_dimention_associative_arr japan_population_arr country_population_arr 10

declare -p country_population_arr | tee -a ${LOG}

declare -A sorted_arr

#mapfile -d '' sorted_arr < <(printf '%s\0' "${!country_population_arr[@]}" | sort -z)
#declare -p sorted_arr | tee -a ${LOG}

print_sorted_associative_arr_by_key "${country_population}" country_population_arr sorted_arr
declare -p sorted_arr | tee -a ${LOG}

country=country.txt
country_population=country_population.txt

print_arr "${country}" "${country_population}" country_arr country_population_arr

⇧ で、実行すると、

⇧ 期待した順番にソートができてそうです。

Bashの仕様なのか分からんけど、ちゃんと格納した順番を維持して欲しいよね...

2次元の配列が無いのも辛いけど、ソートがし辛いのもキツいですな...

一応、Wikipediaによると、

プログラミング

現代の多くのシェルは手続き型プログラミング言語にある基本的な制御フロー構造などに似た豊富な機能を備えている。制御構造、変数、コメント、配列、サブルーチンなどである。それらを使えばかなり洗練されたアプリケーションをシェルスクリプトで書くことも可能である。しかし、シェル言語の多くはデータ型システム、クラス、スレッド、複雑な数学的計算といった高水準言語に見られる機能をほとんどサポートしていない。また、コンパイラや性能重視のインタプリタで実装された汎用言語に比べれば実行速度が遅い。

シェルスクリプト - Wikipedia

⇧ 機能の不足は否めない的な説明になってますから、致し方ないのかね...

www.gnu.org

1.1 What is Bash?

Bash is largely compatible with sh and incorporates useful features from the Korn shell ksh and the C shell csh. It is intended to be a conformant implementation of the IEEE POSIX Shell and Tools portion of the IEEE POSIX specification (IEEE Standard 1003.1). It offers functional improvements over sh for both interactive and programming use.

https://www.gnu.org/software/bash/manual/bash.html

1.2 What is a shell?

A Unix shell is both a command interpreter and a programming language. As a command interpreter, the shell provides the user interface to the rich set of GNU utilities. The programming language features allow these utilities to be combined. Files containing commands can be created, and become commands themselves. These new commands have the same status as system commands in directories such as /bin, allowing users or groups to establish custom environments to automate their common tasks.

https://www.gnu.org/software/bash/manual/bash.html

プログラミング言語としての機能はおまけみたいなものってことなんですかね...

毎度モヤモヤ感が半端ない...

今回はこのへんで。