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

シェルスクリプトで名前空間っぽいことしたい

codezine.jp

github.com

⇧ 是非とも成功して欲しいプロジェクトですな、御武運長久。

シェルスクリプト名前空間っぽいことしたい

シェルスクリプトで、関数などの名前が被るのはNGということで、「名前空間」っぽいことを実現したいと思っていたところ、

yakinikunotare.boo.jp

⇧ 同じようなことを考えておられる先人の方がおりました。

試してみました。

qiita.com

⇧ 上記サイト様を参考にディレクトリ構造とかを表示します。

以下のような、構成。

インプットは、

ts0818.hatenablog.com

⇧ 前回の記事の時と全く同じです。CSVファイルの中身は省略してます。

ID,都道府県市区町村コード,市区町村名,基準メッシュ・コード
T00001,13101,千代田区,53394509
T00002,13101,千代田区,53394518
T00003,13101,千代田区,53394519
T00004,13101,千代田区,53394528

...省略

T03426,13999,境界未定地域,45405294
T03427,13999,境界未定地域,47396763
T03428,13999,境界未定地域,47401024
T03429,13999,境界未定地域,47401034

で、シェルスクリプトの中身は、以下のような感じです。

■/home/ts0818/work/test_validate/validation_csv/func/constants/validate/csv_header.sh

#!/bin/bash

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【定数】
# ■    バリデーション対象のCSVファイルのヘッダーの一覧
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■

csv_header() {
  CSV_HEADER_13() {
    echo ID,都道府県市区町村コード,市区町村名,基準メッシュ・コード
  }
}
    

■/home/ts0818/work/test_validate/validation_csv/func/validate_common.sh

#!/bin/bash

validate_common() {
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数定義】
# ■    共通的なバリデーション処理に関する関数
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】空文字かどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_empty() {
      echo "【start】validate_empty()"
      if [[ -z "$1" ]]; then
          echo "空文字です"
      else
          echo "空文字ではありません"
      fi
      echo "【finish】validate_empty()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】NULLかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_null() {
      echo "【start】validate_null()"
      if [[ "$1" == "NULL" ]]; then
          echo "NULLです"
      else
          echo "NULLではありません"
      fi
      echo "【finish】validate_null()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】全角文字のみかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_full_width() {
      echo "【start】validate_full_width()"
      if [[ "$1" =~ ^[^\x01-\x7E\xA1-\xDF]+$ ]]; then
          echo "全角文字です"
      else
          echo "全角文字ではありません"
      fi
      echo "【finish】validate_full_width()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】半角文字のみかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_half_width() {
      echo "【start】validate_half_width()"
      if [[ "$1" =~ ^[[:ascii:]]+$ ]]; then
          echo "半角文字です"
      else
          echo "半角文字ではありません"
      fi
      echo "【finish】validate_half_width()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】半角数字のみかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_digits() {
      echo "【start】validate_digits()"
      if [[ "$1" =~ ^[0-9]+$ ]]; then
          echo "半角数字です"
      else
          echo "半角数字ではありません"
      fi
      echo "【finish】validate_digits()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】半角英字のみかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_alphabets() {
      echo "【start】validate_alphabets()"
      if [[ "$1" =~ ^[a-zA-Z]+$ ]]; then
          echo "半角英字です"
      else
          echo "半角英字ではありません"
      fi
      echo "【finish】validate_alphabets()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】配列が空かどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_array_empty() {
      echo "【start】validate_array_empty()"
      local -a arr=("${!1}")
      
      if [ ${#arr[@]} -eq 0 ]; then 
          echo "配列は空です";
      else 
          echo "配列は空ではありません";
      fi;
      echo "【finish】validate_array_empty()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】配列の要素が半角数字で、且つ、9桁の固定長であるかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_array_element_legth_all_9() {
      echo "【start】validate_array_element_legth_all_9()"
      local -a arr=("${!1}")
      local valid=true

      for i in "${arr[@]}"; do
          if ! [[ "$i" =~ ^[0-9]{9}$ ]]; then
              valid=false;
              break;
          fi;
      done;

      if $valid; then 
          echo "配列は9桁の半角数字です";
      else 
          echo "配列は9桁の半角数字ではありません";
      fi;
      echo "【finish】validate_array_element_legth_all_9()"
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】配列の要素が半角数字で、且つ、10桁の固定長であるかどうかバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_array_element_legth_all_10() {
      echo "【start】validate_array_element_legth_all_10()"
      local -a arr=("${!1}")
      local valid=true

      for i in "${arr[@]}"; do
          if ! [[ "$i" =~ ^[0-9]{10}$ ]]; then
              valid=false;
              break;
          fi;
      done;

      if $valid; then 
          echo "配列は10桁の半角数字です";
      else 
          echo "配列は10桁の半角数字ではありません";
      fi;
      echo "【finish】validate_array_element_legth_all_10()"
  }
}

■/home/ts0818/work/test_validate/validation_csv/validate_csv_13.sh

#!/bin/bash

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【外部ファイル読み込み】
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# 共通的な関数を定義したファイルを読み込み
source /home/ts0818/work/test_validate/validation_csv/func/validate_common.sh

# CSVファイルのヘッダーの一覧を定義したファイルを読み込み
source /home/ts0818/work/test_validate/validation_csv/func/constants/validate/csv_header.sh


validate_csv_13() {

HEADER=$(csv_header;CSV_HEADER_13)

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数定義】
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルのヘッダー行以外のバリデーション
# ■   @param $1 CSVファイルの1行分
# ■   @param $2 ログファイル
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
function execute_validate() {

  validate_column_01 $1[0] $2 >> $2
  validate_column_02 $1[1] $2 >> $2
  validate_column_03 $1[2] $2 >> $2
  validate_column_04 $1[3] $2 >> $2

}


# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルのヘッダー行に対するバリデーション
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_header() {
    echo -e "【start】validate_header()\n" 1>&2
    echo -e "HEADER:"${HEADER}"\n" 1>&2
    echo -e '$1:'"$1"'\n' 1>&2
    inputHeader=`echo "$1" | sed -e "s/[\r\n]\+//g"`
    isCorrectHeader=1
    if [[ "${inputHeader}" = "${HEADER}" ]]; then
        echo -e "正しいヘッダーです。\n" 1>&2;
        isCorrectHeader=0
        
    else
        echo -e "ヘッダーが不正です。\n" 1>&2;
        isCorrectHeader=1

    fi
    echo -e "${isCorrectHeader}\n" 1>&2
    echo -e "【finish】validate_header()\n" 1>&2
    echo ${isCorrectHeader}
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルの1列目に対するバリデーション
# ■   @param $1 CSVファイルの1列目
# ■   @param $2 ログファイル
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_column_01() {
    echo -e "【start】validate_column_01()\n" >> $2
    # 必須チェック
    validate_common;validate_empty "$1"
    
    
    echo -e "【finish】validate_column_01()\n" >> $2
  }
  
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルの2列目に対するバリデーション
# ■   @param $1 CSVファイルの2列目
# ■   @param $2 ログファイル 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_column_02() {
    echo -e "【start】validate_column_02()\n" >> $2
    # 必須チェック
    validate_common;validate_empty "$1"
    # 数値のみかチェック
    validate_common;validate_digits "$1"
    
    echo -e "【finish】validate_column_02()\n" >> $2
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルの3列目に対するバリデーション
# ■   @param $1 CSVファイルの3列目
# ■   @param $2 ログファイル
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_column_03() {
    echo -e "【start】validate_column_03()\n" >> $2
    # 必須チェック
    validate_common;validate_empty "$1"
    # 全角文字のみかチェック
    validate_common;validate_full_width "$1"
    
    echo -e "【finish】validate_column_03()\n" >> $2
  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルの4列目に対するバリデーション
# ■   @param $1 CSVファイルの4列目
# ■   @param $2 ログファイル
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
  function validate_column_04() {
    echo -e "【start】validate_column_04()\n" >> $2
    # 必須チェック
    validate_common;validate_empty "$1"
    # 数値のみかチェック
    validate_common;validate_digits "$1"
    
    echo -e "【finish】validate_column_04()\n" >> $2
  }
}

■/home/ts0818/work/test_validate/validation_csv/validate_csv_main.sh

#!/bin/bash

#export LANG=ja_JP.sjis

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【外部ファイル読み込み】
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# 各CSVファイルのバリデーション関数を定義したファイルを読み込み
source /home/ts0818/work/test_validate/validation_csv/validate_csv_13.sh

# CSVファイルのヘッダーの一覧を定義したファイルを読み込み
source /home/ts0818/work/test_validate/validation_csv/func/constants/validate/csv_header.sh

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【変数定義】
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
log=/home/ts0818/work/test_validate/validation_csv/log/debug.log


# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数定義】
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
validate_csv_main() {

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルのバリデーションを実行
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
#  function main() {
  main() {
    echo "【start】main()"
    echo '$1'$1 >> ${log}
    # バリデーションを選択
    selectValidate=$(select_validate $1)
    
    echo 'selectValidate:'${selectValidate} >> ${log}

    # 選択されたバリデーションの処理を実施する
    if [ 13 -eq ${selectValidate} ]; then
        rowCount=1
        while IFS=, read -r -a row; do
            echo -e "■${rowCount}行目のバリデーションを開始します。■" >> ${log}
            validate_csv_13;execute_validate ${row} ${log}
            echo -e "■${rowCount}行目のバリデーションを終了します。■" >> ${log}
            # 行数をインクリメント
            rowCount=$((rowCount+1))
        done < $1
    else
        echo "バリデーションの処理が行われませんでした。"
    fi

    echo "【finish】main()"

  }

# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【関数】CSVファイルのバリデーションを選択
# ■   @param $1 
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
#  function select_validate() {
  select_validate() {
    echo -e "【start】select_validate()\n" 1>&2
    echo "【start】select_validate()" >> ${log}
    while read -r -a row; do
      echo 'row:'${row} >> ${log}
      validateHeader=`validate_csv_13;validate_header ${row}`
      echo -e 'validateHeader:'${validateHeader}"\n" 1>&2
      if [ 0 -eq ${validateHeader} ]; then
        echo 13;
        break;
      else
        echo 255;
        break;
      fi
    done < $1
  }

}


# ■■■■■■■■■■■■■■■■■■■■■■■■■■■
# ■ 【処理】
# ■■■■■■■■■■■■■■■■■■■■■■■■■■■

targetDir=/home/ts0818/work/test_validate/data/file/csv
for file in `\find ${targetDir} -name '*.csv'`; do
    # 
    validate_csv_main;main $file
done

⇧ で実行すると、

⇧ バリデーションの内容は兎も角として、処理自体は行われているようです。

バリデーション処理は、Microsoft Bingの提案をそのまま使ったから、勿論動いて無さそうね...AIさん平気で嘘付くからなぁ…

う~む、シェルスクリプトだと、Pythonより更にバリデーションの実装に辛みがあるような...

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

今回はこのへんで。