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

シェルスクリプトでCSVファイルを読み込んでみる

gigazine.net

OpenAIは当初から、ChatGPTは「それっぽいけれど間違ったことを出力することがある」と警告し続けていて、学術誌や国際会議では使用を禁止しているところもあります。

ChatGPTが虚偽の出力をしたとして名誉毀損で訴えられる - GIGAZINE

⇧ 間違いというか、捏造されてるのが問題な気がするけど...

■間違い

■捏造

ちなみに、

捏造(ねつぞう(慣用読み)、でつぞう)は、実際になかったことを故意に事実のように仕立て上げること。「捏」の読み方は古くは「デツ」であるため、でっち上げの語源ともなっている。

捏造 - Wikipedia

⇧『でつぞう』が本来の正しい読み方だったらしい。

何故、AIの回答が「捏造」されたものになることがあるかについては、

gigazine.net

⇧ 上記の記事が詳しいですかね。

我々ができることとしたら、必ず、回答に至った一次情報のURLを連携してもらって情報の妥当性を検証するしかないってことですかね...

Microsoft Bingも平気で嘘付くからね...

シェルスクリプトCSVファイルを読み込んでみる

前回、

ts0818.hatenablog.com

Oracle Databaseの機能で、CSVファイルを読み込んでOracle DatabaseのテーブルにINSERTしてみました。 

今回は、シェルスクリプトCSVファイルを読み込んでみようと。

で、

unageanu.hatenablog.com

CSVにはヘッダーが付いている場合がある訳ですが、形式がデータ行と同じなので、文字列だけ見ても判断が付きません。これについて仕様書によると、MIME Typeのパラメータで判定しましょうとのこと。具体的には、以下のようになります

  ヘッダーがある場合   text/csv; charset=utf-8; header=present
  ヘッダーがない場合   text/csv; charset=utf-8; header=absent

ちなみに、文字コードMIME Typeパラメータで判定するという話になっています。

CSVのあれやこれや - うなの日記

⇧ 上記サイト様によりますと、CSVファイルのヘッダーの有無について考慮する必要があることが分かりますと。

で、困ったことに、HTTPリクエストみたいな形でCSVファイルを連携された場合は、MIME Typeのパラメーターで判定できるのかもしれないですが、アップロードとか済んでいて既に配置済みのCSVファイルについては、ヘッダーを含んでいるかどうかをMIME Typeのパラメーター(header=present)で判定するのは無理っぽい。

とりあえず、CSVファイルの読み込みを試してみた。

改行コードを含むかどうかの判定などは、

unix.stackexchange.com

⇧ 上記サイト様を参考。

#!/bin/bash

if [ -z "$1" ]; then
  echo "CSVファイルを指定してください"
  exit 1
fi

if ! [ -f "$1" ]; then
  echo "CSVファイルが存在しません"
  exit 1
fi

# CSVファイルかチェック
if ! file -b --mime-type "$1" | grep -q "^text/csv"; then
  if [ "$(head -c3 "$1")" = $'\xef\xbb\xbf' ]; then
    tail -c +4 "$1" > "$1.tmp" && mv "$1.tmp" "$1"
  elif [ "$(head -c4 "$1")" = $'\xff\xfe\x00\x00' ]; then
    tail -c +5 "$1" > "$1.tmp" && mv "$1.tmp" "$1"
  elif [ "$(head -c4 "$1")" = $'\x00\x00\xfe\xff' ]; then
    tail -c +5 "$1" > "$1.tmp" && mv "$1.tmp" "$1"
  elif [[ "$(basename -- $1)" == *.csv ]]; then
    echo "CSVファイルです"
  else
    echo "CSVファイルではありません"
    exit 1
  fi
fi

# 位置パラメーターを変数に格納
readonly input_csv_file=$1

# CSVファイルのヘッダー有無のチェック用
readonly csv_header_column_list="FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME"

header_cols=()
row_index=0
# CSVファイルの読み込み開始
# CSVファイルの行数分、繰り返し
while read line; do

  # 改行コードを削除
  line=`echo $line | sed -e "s/\\r//g" -e "s/\\n//g"`

  # 改行コードが含まれていないかチェック
  if [[ $line == *$'\r'* ]]; then
    echo "includ newline.";
  fi
  
  # 文字数の確認
  echo 'STRING LENGTH: ' ${#line}'$line: '"$line"
  echo 'STRING LENGTH: ' ${#csv_header_column_list}'$csv_header_column_list: '"${csv_header_column_list}"

  # ヘッダー行だった場合
  if [ "$line" = "${csv_header_column_list}" ]; then
      echo "$line"
      echo "${csv_header_column_list}"
      echo "header row."
      line=$(echo -n ${line} | sed 's/=//g')
      IFS=',' read -ra header_cols <<< "$line"
      continue
  fi

  # 1行分を配列に格納
  IFS=',' read -ra cols <<< "$line"

  # カラム数のチェック
  if [ -z "${cols[0]}" ] \
    || [ -z "${cols[1]}" ] \
    || [ -z "${cols[2]}" ] \
    || [ -z "${cols[3]}" ] \
    || [ -z "${cols[4]}" ] \
    || [ -z "${cols[5]}" ] \
    || [ -z "${cols[6]}" ]; then
      echo "CSVファイルの要素数が異なります"
      exit 1
  fi

  # ヘッダー行では無い場合
  # 行数を表示
  row_index=`expr ${row_index} + 1`
  echo "${row_index} line"
  
  # 1行分を表示
    echo "$(cat <<EOF
    ${header_cols[0]}=${cols[0]}
    ,${header_cols[1]}=${cols[1]}
    ,${header_cols[2]}=${cols[2]}
    ,${header_cols[3]}=${cols[3]}
    ,${header_cols[4]}=${cols[4]}
    ,${header_cols[5]}=${cols[5]}
    ,${header_cols[6]}=${cols[6]}
EOF
)"
done < ${input_csv_file}

⇧ 上記のファイルを、「WSL 2(Windows SubSystem for Linux 2)」の「Oracle Linux 8.7」の環境に配置。

で、実行。

sudo sh ./read_csv_file.sh $HOME/insert-W_M_FACILITY.csv
CSVファイルです
STRING LENGTH:  78$line: FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
STRING LENGTH:  78$csv_header_column_list: FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
header row.
STRING LENGTH:  91$line: 001,H,パークハイアット東京,163-1055東京都新宿西新宿3-7-1-2,0353221234,2023/06/11 00:00:00,2023/06/11 00:00:00
STRING LENGTH:  78$csv_header_column_list: FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
1 line
    FACILITY_CODE=001
    ,FACILITY_CLASS=H
    ,FACILITY_NAME=パークハイアット東京
    ,ADDRESS=163-1055東京都新宿西新宿3-7-1-2
    ,TEL=0353221234
    ,CREATE_TIME=2023/06/11 00:00:00
    ,UPDATE_TIME=2023/06/11 00:00:00
STRING LENGTH:  87$line: 002,H,コンラッド東京,160-0023東京都新宿区西新宿2-2-1,0363888000,2023/06/11 00:00:00,2023/06/11 00:00:00
STRING LENGTH:  78$csv_header_column_list: FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
2 line
    FACILITY_CODE=002
    ,FACILITY_CLASS=H
    ,FACILITY_NAME=コンラッド東京
    ,ADDRESS=160-0023東京都新宿区西新宿2-2-1
    ,TEL=0363888000
    ,CREATE_TIME=2023/06/11 00:00:00
    ,UPDATE_TIME=2023/06/11 00:00:00
STRING LENGTH:  89$line: 003,H,京王プラザホテル,163-1055東京都新宿西新宿3-7-1-2,0333440111,2023/06/11 00:00:00,2023/06/11 00:00:00
STRING LENGTH:  78$csv_header_column_list: FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
3 line
    FACILITY_CODE=003
    ,FACILITY_CLASS=H
    ,FACILITY_NAME=京王プラザホテル
    ,ADDRESS=163-1055東京都新宿西新宿3-7-1-2
    ,TEL=0333440111
    ,CREATE_TIME=2023/06/11 00:00:00
    ,UPDATE_TIME=2023/06/11 00:00:00
STRING LENGTH:  90$line: 004,H,ホテルニューオータニ,102-0094東京都千代田区紀尾井町4-1,0332651111,2023/06/11 00:00:00,2023/06/11 00:00:00
STRING LENGTH:  78$csv_header_column_list: FACILITY_CODE,FACILITY_CLASS,FACILITY_NAME,ADDRESS,TEL,CREATE_TIME,UPDATE_TIME
4 line
    FACILITY_CODE=004
    ,FACILITY_CLASS=H
    ,FACILITY_NAME=ホテルニューオータニ
    ,ADDRESS=102-0094東京都千代田区紀尾井町4-1
    ,TEL=0332651111
    ,CREATE_TIME=2023/06/11 00:00:00
    ,UPDATE_TIME=2023/06/11 00:00:00

コマンドプロンプトが悪いのか、「WSL 2(Windows SubSystem for Linux 2)」が悪いのか、文字の豆腐化が起きてしまってますが、CSVファイルの読み込みが出てきたようです。

それにしても、シェルスクリプトの変数に改行コードが含まれているかどうかのチェックとか、もう少し分かりやすくする方法ないものか...

あと、CSVファイルの項目数が多くなってきた場合、記述量が増えるのは致し方ないってことなんですかね...

CSVファイルのヘッダーの有無のチェックって、結局どうするのが良いのか分からん...

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

今回はこのへんで。