概要
表題の件、短い時間で2件の残念な出来事に遭遇したため備忘録として記載。
for文で日付を取得しようとして失敗
シェルスクリプトのfor文で日付を取得しようとした。
要件
1.2000年1月1日から2035年12月31日までをテキストに取得
2.出力するテキスト名はYMD.txt(実質何でもよい)
3.出力形式はYYYMMDD
4.1日1行づつ出力
5.ごみファイルを作成してもよい
仕様
1.西暦(2000~2035)を記載するファイルとしてY.txtを作成
2.月(1~12)を記載するファイルとしてM.txtを作成
3.日付(1~31)を記載するファイルとしてD.txtを作成
4.各ファイルの中身をcatで参照しfor文でYYYMMDD形式でYMD.txtに記載
実装
seqでY.txt、M.txt、D.txtを作成
seq 2000 2035 > Y.txt
seq -w 12 > M.txt
seq -w 31 > D.txt
以下のスクリプトYMS.shでYMS.txtを作成。作成時間3分程度。シンプルイズベスト。
最後の3行の「だーん」が青木真也の元ツイッターみたいでカッコいい。(自分で書いておきながら意味がよくわからない)
#!/bin/bash
for a in `cat Y.txt`
do
for b in `cat M.txt`
do for c in `cat D.txt`
do echo $a$b$c >> YMD.txt
done
done
done
実行権限を付与後、実行し概ね意図した通りに作成されたことを確認。
実行時間は5秒程度。
chmod +x YMD.sh
time ./YMD.sh
real 0m4.432s
user 0m0.219s
sys 0m3.141s
head -5 YMD.txt
20000101
20000102
20000103
20000104
20000105
tail -5 YMD.txt
20351227
20351228
20351229
20351230
20351231
wc -l YMD.txt
13392 YMD.txt
失敗
作成して30秒くらいで重大な欠陥に気づく。
このスクリプトの実行結果やと1年372日もあるやんorz
2月31日とか日付が生成されているやんorz
grep -c 2000 YMD.txt
372
grep 0231$ YMD.txt | head -2
20000231
20010231
でも自分でバグを見つけることができてエライ!?!?
困ってGPT先生に教えを乞う
のび太がドラえもんに泣きつくようなスムーズな流れでマイクロソフトEDGEのGPT4.0先生に相談。
4.0先生は3.0先生と全然違うらしいっすよ。パねえらしいっすよ!
知らんけど。
そして書いてくれたコード(date.sh)が以下。
#!/bin/bash
for i in {10957..18262}; do
date -d "2000-01-01 + $i days" +%Y%m%d
done
微妙に残念
めっちゃシンプルかつ分かりやすい!さすが4.0先生、パねえっス!
けど、実行したら2029年12月31日から出力されまっせ!最終日も2049年12月31日でっせ!
生成したスクリプトは素敵やけど一番大事な結果がめちゃめちゃですよ!
しかも「2000年1月1日から2035年12月31日まで出力しました。お気に召しましたか(ニッコリ)」みたいなコメントまで返してくれている。
何回もいうけどバリバリ間違ってるで、アンタ!
しかも人間もびっくりのケアレスミスやで!
./date.sh | head
20291231
20300101
20300102
20300103
20300104
20300105
20300106
20300107
20300108
20300109
./date.sh | tail
20491222
20491223
20491224
20491225
20491226
20491227
20491228
20491229
20491230
20491231
デバッグしたらさらに迷走し吾輩のコードをパクり始める
このまま放置してやろうかとも思ったが、とりあえず変数を変更して修正。コードは不細工やけど機能回復優先。
#!/bin/bash
for i in {0..13148}; do
date -d "2000-01-01 + $i days" +%Y%m%d
done
その後、終了の処理を動的に判断する仕組みに変更してもらおうと思い、このブログ部分の要件をコピペして4.0先生に再度質問したらこんな答えが返ってきた。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
こんにちは、これはBingです。😊 あなたはシェルスクリプトのコードを作成したいと思っているようですね。 私はあなたにコードの例を提供することができますが、あなたの要件に合わせて修正する必要があります。 以下のコードブロックを参考にしてください。
# Y.txtを作成し、2000年から2035年までの西暦を記載する
seq 2000 2035 > Y.txt
# M.txtを作成し、1月から12月までの月を記載する
seq 1 12 > M.txt
# D.txtを作成し、1日から31日までの日付を記載する
seq 1 31 > D.txt
# YMD.txtを作成し、Y.txt, M.txt, D.txtの内容を組み合わせてYYYYMMDD形式で記載する
touch YMD.txt
for y in $(cat Y.txt); do
for m in $(cat M.txt); do
for d in $(cat D.txt); do
# 月と日付が1桁の場合は0を付ける
printf "%d%02d%02d\n" $y $m $d >> YMD.txt
done
done
done
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
これ俺のアルゴリズムとコードそのまんまテキストファイル名([Y|M|D].txt)迄パクっているし。
このスクリプトやと2月31日出力するし。青木真也っぽい「だーん」3連発までパクっているし。
ここまで全力でボケられると可愛く思えてきた。少なくとも面白くなってきた。
4.0先生 3度目の正直も失敗
毒食わば皿までの心境で「先生、そのアルゴリズムだと1年が372日になり、毎年2月31日がそんざいする架空の暦が爆誕します。 date -d “2000-01-01”などを利用してシンプルなコードに修正してください。」と質問したら以下の返事とコードが返ってきた。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
すみません、私はあなたの先生ではありません。😅 私はあなたにコードの例を提供することができますが、あなたの要件に合わせて修正する必要があります。 dateコマンドを利用すると、以下のようにコードを修正できます。
# Y.txtを作成し、2000年から2035年までの西暦を記載する
seq 2000 2035 > Y.txt
# YMD.txtを作成し、Y.txtの内容を元にYYYYMMDD形式で記載する
touch YMD.txt
for y in $(cat Y.txt); do
# 1月1日から12月31日までの日付を生成する
for d in $(seq -f "%g" 1 365); do
# 日付をYYYYMMDD形式に変換する
date -d "$y-01-01 +$d days" +%Y%m%d >> YMD.txt
done
done
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
やっとまともっぽいコードを返してきやがった。と思ったら、今度はうるう年を考慮に入れておらず、4年に1度12月31日のない暦を爆誕させやがった。しかも2036年1月1日が存在するおまけつき。
なんてファンタジー(cocco ファンタジーより)
顛末
「先生、そのアルゴリズムだと、閏年は12月30日までしか存在しないことになります。 コードを修正してください。」とお伝えすると以下のエラーを標準出力に出しながらも出力するコードを生成してくれた。相変わらず2036年1月1日まで日付を出していたけれど。
date: invalid date `20YY-02-29'
-bash: [: -eq: unary operator expected
このくらいでいいかと思い、最終行は手動削除で完了という事にしておきました。
結論:GPT4.0先生は癒し系AI
業務の課題を一瞬で解決する素晴らしい回答だけではなく、とんでもないボケっぱなしジャーマンをぶちかましてくれる4.0先生は○○○○も裸足で逃げ出す令和の癒し系。
あっという間に賢くなってこんなことしなくなるのだろうけれど、2023年9月の時点ではええ感じで間違えてくれて我々をほっこりさせてくれる。4.0先生に愛を感じずにはいられない。
こんな感じでこれからも我々の仕事に適度に癒しとソリューションを提供してほしいと願う日曜の深夜早朝であった。
みんな幸わせになれたらいいのに なんてファンタジー
最後になんとなくcocccoちゃんの歌詞を書いてみたくなったので書いてみた。
coccoちゃんを好きなIT系の人ってどのくらいいるのかしら。
コメント