初めてシェルスクリプトで効率化を行ったので、メモがてら。
簡単で単純なコマンドでも、知らなければめちゃくちゃ難しく感じるものですよね。
なるべく端折らずに書きます(。・ω・)φ.....
##スクリプトがやっていること
1)受け取った引数が適当な形式かチェック
2)対象txtファイルの存在の有無をチェック (複数あるので基本ループ↓)
3)txtの内容の上部下部それぞれ3行ずつ表示して確認する
4)中身の1行目を削除するかのyes/no選択
5)1行目を削除しつつコピーを生成する
6)コピー物を融合し一つにまとめる
7)結果をログtxtとして書き出す(複数行を一括書き)
8)次のシェルスクリプトを呼ぶ
####その他豆知識
* コメントを複数行書きたいけど、「#」をあんま書きたくない
* 次のコマンドの実行を、指定した時間分遅らせたい
【 引数の確認 (引数が3つある前提) 】
引数 | 説明 | 例 |
---|---|---|
1つ目 | YYYYMMDD形式の日にち | 20200131 |
2つ目 | ファイルの個数 | 3 |
3つ目 | 実際には使わないので途中から省略 | 0 |
__個数のチェック____
「$#」 …引数の個数をもつ変数。デフォルトである変数。
if [ $# -ne 3 ]; then
echo " 指定された引数は$#個です。実行するには引数3個を指定してください。" 1>&2
fi
__文字数のチェック____
1つ目の変数を、YYYYMMDD形式で入力してほしい(8文字)。
「${#1}」 …引数1つ目の文字数を表す。デフォルトである変数。
if [ ${#1} -ne 8 ] ; then
echo " 指定された引数の長さが8バイトではありません。" 1>&2
fi
__日付として妥当かチェック____
1つ目の変数が、日付として妥当かどうか。(仕組みはわかんないけどこれでできた)
「$?」 …直前の変数を指す。ここでは、「${1}」
date -d "${1}" 2>/dev/null
if [ $? -ne 0 ] ; then
echo " 指定された引数は日付として妥当ではありません。" 1>&2
fi
【 txtファイルの存在の確認(引数分ループ) 】
__AAA_1.txt AAA_2.txt AAA_3.txt (引数2つ目で「3」と指定)___
引数で指定した数字分ループさせる。
「$2」 …2つ目の引数をもっている。デフォルトである変数。
「$i」 …ループカウントするための変数。自作変数。ファイル名にある数字に呼応するようにしてある。
for i in `seq $2`; do
if [ ! -f AAA_$i.txt ]; then
echo " AAA_"$i".txtが存在しません。" 1>&2
fi
done
###【 AAA.txtの上部3行 表示(引数文ループ) 】
引数で指定した数字分ループし、内容最初3行分をさせる。
下部3行分表示したければ、「head」を「tail」に変えればいい。
for i in `seq $2`; do
cat AAA_"$i".txt | head -n 3
done
###【 内容頭1行目を削除するか否かの選択 】
「yes」「YES」「no」「NO」に対応。「yEs」とかひねくれた返答にも一応対応。
それ以外の文字は反応せず、ループして聞き返す仕様。
※Noを選択しても、プログラムは終了せず、次のコマンドへ飛ぶようになっている。
「$yn」 …返答を格納する変数。自作。
echo " ____◇◆◇◆ Message ◇◆◇◆___________"
echo " 一行目を削除しますか? "
echo " 消す→「yes」 消さない→「no」 "
echo " ________________________________________"
while :
do
read -p "----> " yn
case "$yn" in
[yY][eE][sS] ) echo " 削除して統合します。"
break;;
[nN][oO] ) echo " 削除しないまま統合します。"
break;;
*) ;;
esac
done
###【 一行目を削除しコピーを生成する(引数分ループ) 】
「$yn」に入っている文字数(yes/no)でif分岐させる。
3文字なら「yes」なので、削除する。
####削除するver
if [ ${#yn} -eq 3 ] ; then
for i in `seq $2`; do
sed -e '1d' AAA_$i.txt > AAA_$i.txt.copy
done
fi
####削除しないver(ただのコピー)
if [ ${#yn} -eq 2 ] ; then
for i in `seq $3`; do
cp AAA_$i.txt AAA_$i.txt.copy
done
fi
###【 統合させて1つのファイルにする 】
コピー物(~.txt.copy)を全て、TOTAL.txtとしてまとめる。
ちなみに、さらにTOTAL.txtに追加で統合させたくなったら、「>」を「>>」にすれば、追加できる。
cat *.txt.copy > TOTAL.txt
###【 Log_YYYYMMDD.txtに変化過程を排出】
{} で囲って、「>> Log_$1.txt」で締めくくれば、その指定ファイルに{}内のコマンドが出力される。
今回は引数1つ目のYYYYMMDDファイル名に取り入れたかったため、「$1」をファイル名に挟んである。
※{}は改行しておかないと無効化されるので注意。
ここで出力しているのは、
1)初めの、無加工状態のファイル内データの行数(ループ)
2)1行削除が行われたコピー物のデータの行数(ループ)
3)コピー物を融合させた、TOTAL.txtの行数
少し見やすいようデザインを入れてある。
コマンド「wc」は、そのファイル内の行数を出してくれるコマンド。
{
echo "<<<<<AAA.txt 変化確認>>>>>"
for i in `seq $2`; do
wc -l AAA_$i.txt
done
echo "↓"
for i in `seq $2`; do
wc -l AAA_$i.txt.copy
done
echo "-----------------------"
wc -l TOTAL.txt
echo "-----------------------"
echo -e "\n\n"
} >> Log_$1.txt
###【 次のシェルスクリプトを呼んで引き継ぐ 】
引数1つ目であるYYYYMMDDを継承し、次のシェルスクリプト「next_shell.sh」へ自動移行する。
sh next_shell.sh "${1}"
## ●他 豆知識
#### 【コメントを複数行書きたい。#は乱用したくない】
「READme」部分は、各自好きなキーワードに変更可能。
そのキーワードを行の先頭に置いた箇所が、コメントの終わり部分になる。
:<< "READme"
ここにコメントを好きなだけ書く
ここにコメントを好きなだけ書く
ここにコメントを好きなだけ書く
ここにコメントを好きなだけ書く
READme
#### 【次のコマンドの実行を、指定時間分遅らせたい】
sは秒数。
echo "この後10秒停止する"
sleep 10s
echo "10秒後にこのechoが表示される"
以上です!
時間があれば、実行権限のも書く予定です。
ありがとうございました。