◇bashメモ:いくつかの雛形
緊急メモです。書きかけです。m(_ _)m
bashの壁
bashは機械による構文解析を容易にするため、人間向きではない記述法がとられています。
複雑で覚えるのも大変で、正確に繰り返すことは極めて困難です。
本記事は「雛形」としてコピペで使うためのものですが、いくつかの注意点を最初に上げておきます。
空白
bashで最も難しいのは空白です。
空白に関しては何十年もやっているのにいまだになれることができません。
例えば次の記述は思う通りの動作はしません。
TARGET = ABC # 変数定義の=前後に空白があってはならない if [ "$ans"=="x" ];then # ==の前後には空白が必要 exit 0 fi if ["$ans" == "x"];then # [の後,]の前には空白が必要 exit 0 fi
$*を使ってはならない (空白を含む引数対応)
下位のシェルを呼び出すとき、絶対に$*を使ってはいけません。
$*を使うと引用符で囲まれ空白を含む引数が空白で分断された別の引数となってしまいます。
必ず"$@"($@をダブルクオートで囲む)を使う事。
- - - - - - - - - - - - - - - - test_main.sh - - #!/bin/bash echo ===== test_main.sh ===== for P in "$@"; do echo $P; done echo call 'test_sub $*' ./test_sub.sh $* echo call 'test_sub "$@"' ./test_sub.sh "$@" - - - - - - - - - - - - - - - - test_sub.sh - - #!/bin/bash echo ----- test_sub.sh ----- for P in "$@"; do echo $P; done - - - - - - - - - - - - - - - - 実行 - - $ ./test_main.sh a "b c" d ===== test_main.sh ===== a b c d call test_sub $* ----- test_sub.sh ----- a b # b cが別の引数となった c d call test_sub "$@" ----- test_sub.sh ----- a b c # b cが空白を挟む一つの引数となった d
これはついやってしまう大きな落とし穴です。ある日あれっ?となる。
改行とセミコロン
if...then...fiの制御文は行を分ける必要があります。
同一行に置く場合はセミコロンを入れなければなりません。
./doSomething if [ $? -ne 0 ] then echo ERROR OCCURED! exit 1 fi # ./doSomething if [ $? -ne 0 ];then echo ERROR OCCURED!;exit 1;fi
while...do...doneなども同じです
リダイレクト
標準出力と標準エラー出力をまとめるには次の異常極まりない記述が必要です。絶対に覚えることができません。
rm *.bak > /dev/null 2>&1
文字列、数値と変数
変数の参照は$の後ろに変数名を書きます。EX) $var
{}で囲んでも構いません EX) ${val}
明示的に文字列にしたい場合、引用符で囲みます。 EX) "${val}
変数を文字列と比較する場合は変数を引用符で囲む必要があります。
値の比較法は文字列と数値では異なります。
文字列比較 ( == != ) if [ "${txt}" == "ABC" ]; then doSomething; fi 数値比較 ( -eq -ne -lt -le -gt -ge ) if [ ${num} -le 100 ]; then doSomething; fi
上の例では${txt}を引用符で囲んであります。囲んでいない場合$txtに数値が入るとおおよそ人間には理解不能なエラーとなります。
文字列の連結と変数参照
文字列連結には+などは不要です。ダブルクオートの中に置いた変数も展開されます。シングルクオートで囲むと変数は展開されません。空白が必要な場合は引用符内に置きます。
txt=ABC echo '${txt}='${txt} --> $txt=ABC txt=ABC echo "${txt}="${txt} --> ABC=ABC txt=ABC echo '${txt} = '${txt} --> ${txt} = ABC
複雑怪奇な記号[(の組み合わせ
- 未稿 -
基本雛形
自身のフォルダを取得
#!/bin/bash
# UTF-8 LF bashは改行がLFでないとエラーになるのでコメントしておく
THIS_DIR=$(cd $(dirname ${BASH_SOURCE:-$0}); pwd) # フルパスで得られる
cd ${THIS_DIR}
ここでは$(コマンド;コマンド;コマンド)により、最後のコマンド出力を変数に取り込んでいます。
for文/while文
- 未稿 -
引数チェック雛形
コマンド引数をチェックし、対象以外の引数を残す雛形を載せます。
この例ではチェックに引っかからなかった引数を配列 $argv に残してます。
#------------------------------------------------------- # -y/-v 数値 オプション抜き出し #------------------------------------------------------- ALLYES="n" ans="n" v="0" argv=() #--- コマンドオプションの抜き出し.残りは${arg[@]}でえられる declare -a org_args for a in $@;do org_args=("${org_args[@]}" $a) done for (( i = 0; i < ${#org_args[@]}; i++ ));do a="${org_args[$i]}" if [ $a == "-y" ];then ALLYES="y" ans="y" elif [ $a == "-v" ];then v=$i+1 v="${org_args[$i]}" else argv+=($a) fi done #echo ans=${ans} v=${v} #for a in ${argv[@]} ;do echo $a; done
キー入力チェック雛形
確認メッセージを出しキー入力をチェックする雛形です。
ここではコマンド引数に"-y"があう場合は確認待ちをしないようにしてあります(コマンド引数"-y"は前項でチェックされているものとしています)
"y","n","x"が入力されるまで繰り返します。これは間違いを防ぐため極めて重要です。
if [ ${ALLYES} != "y" ];then while true ;do read -p "doSomethinを実行しますか? (y/n/x) " ans if [[ "${ans}" =~ y|n|x ]];then break;fi done fi if [ "${ans}" == "x" ];then echo bye!;exit 0;fi if [ "${ans}" == "y" ];then ./doSomething if [ $? -ne 0 ];then echo ERROR OCCURED!;exit 1;fi fi
その他:すぐ忘れる事柄
ファイルの途中行を抜き出す
ファイルの先頭や尾部を抜き出すにはhead,tailが使えますが、途中を抜き出すにはawkを用います。
# data.txtファイルの143000行から143100行を抜き出す awk "NR==143000,NR==143100 {print}" data.txt
| 固定リンク