内容へ移動
Cat Paw Software
ユーザ用ツール
ログイン
サイト用ツール
検索
ツール
文書の表示
以前のリビジョン
バックリンク
最近の変更
メディアマネージャー
サイトマップ
ログイン
>
最近の変更
メディアマネージャー
サイトマップ
トレース:
shellscript
この文書は読取専用です。文書のソースを閲覧することは可能ですが、変更はできません。もし変更したい場合は管理者に連絡してください。
====== ShellScript ====== ===== bash ===== シェルスクリプトは基本的にはbashをターゲットに作成する。 <code> #!/bin/bash -eu ... </code> shebangは''#!/bin/sh''にはしない dockerで起動する場合、alpineにはbashが入ってないため、ubuntu-slimをベースイメージにする。 ===== shの実行オプション ===== * -e 実行時コマンドが失敗したら(ステータス0以外を返したら)以降の処理を打ち切る * -x 変数を展開した状態で実際に実行されるコマンドを標準エラー出力に書き出す * -u 未定義の変数があれば処理を打ち切る * -C noclobberオプションを有効にする(リダイレクトでファイルを上書きしようとするとエラーになる、追記はOK) shebangに追加されることが多い <code sh> #!/bin/bash -uex ... </code> ===== testコマンド ===== <code shellscript> test -f ./hoge.txt && echo "hoge.txtあるよ" if [ -f ./hoge.txt ]; then echo "hoge.txtあるよ" fi if [[ -f ./hoge.txt ]]; then echo "hoge.txtあるよ" fi </code> * -e ファイルが存在すればtrue * -f 通常ファイルならtrue * -d ディレクトリならtrue * -L シンボリックリンクならtrue * -r 読み込み可能ならtrue * -w 書き込み可能ならtrue * -x 実行可能ファイルならtrue * -z 文字列長が0ならtrue * -n 文字列長が0でなければtrue * -t 指定した番号のファイルディスクリプタが開かれていればtrue ==== [[ ]] ==== testコマンドのbash拡張 単語分割やパス展開しないので、変数をクオートで囲む必要ない <code sh> $ HOGE="a b c" $ [ $HOGE == "a b c" ] && echo "一致" bash: [: too many arguments $ [[ $HOGE == "a b c" ]] && echo "一致" 一致 $ HOGE=hoge.* $ [ $HOGE == "hoge.*" ] && echo "一致" || echo "不一致" 不一致 $ [[ $HOGE == "hoge.*" ]] && echo "一致" || echo "不一致" 一致 </code> ===== read ===== 標準入力から1行読み取る read line echo $line プロンプトを出して入力を促す echo -n "User Name: " read username echo $username zshでは以下のようにかける read "username?User Name: " echo $username 入力値をマスクしたい場合はread -s(決定時の改行も出力されなくなるのでechoを挟むとよい) read -s "password?Password: " tty -s && echo echo $password | shasum -a 256 標準入力が尽きるまで行を読み取る(Ctrl-DでEOFを送信) while read line do echo $line done ファイルから行を読み込みする while read line do echo $line done < hoge.txt ヒアドキュメントから行を読み込みする while read line do echo $line done << EOS 1 2 3 EOS ===== trap ===== ==== シグナルのハンドリング ==== <code> trap "echo trap sigint" INT while :; do sleep 1; done </code> SIGINTをトラップすると、Ctrl-cで終了できなくなるので注意。またSIGKILLはトラップできない。 ==== EXITで終了時処理 ==== 基本はシグナルのハンドリングだが、EXITとERRという疑似シグナルが利用できる。例えばmktempで作成した一時ファイルをスクリプト終了時に削除するなどの処理をEXITと組合わせて書ける。 <code> hoge=/tmp/hogehoge mktemp $hoge trap "rm $hoge" EXIT </code> ===== テクニック ===== ==== スクリプトファイル名を取得 ==== <code bash> FILENAME=$(basename $0) FILENAME=${0##*/} </code> ==== スクリプトのディレクトリを取得 ==== カレントディレクトリにかかわらず、スクリプトが存在するディレクトリを取得する <code bash> DIR=$(cd $(dirname $0); pwd) </code> ==== コマンドの存在チェック ==== 「コマンド hoge が PATH にあれば…」の条件分岐 <code bash> if [ -x "$(which hoge)" ]; then echo "hogeあるよ" fi </code> ==== ランダム文字列を生成 ==== 0-9A-Za-zのランダムな文字列を作成する。mac用 <code> $ cat /dev/random | base64 | fold -w 16 | egrep -v "[+/]" | head -n 1 $ head -c 100 /dev/random | base64 | tr -d "+/" | head -c 16 </code> セキュアな必要がないならば <code> $ shasum <(ls -al) | cut -d " " -f 1 </code> ===== 変数参照 ===== <code> ${HOGE:-wang} # HOGEに値がある場合はその値が展開される。HOGEが空の場合は、wangが展開される ${HOGE:+wang} # HOGEに値がある場合はwangが展開される。HOGEが空の場合は何もしない ${HOGE:=wang} # HOGEに値がある場合はその値が展開される。HOGEが空の場合は、wangと展開し、さらにHOGEにwangを代入 ${HOGE:?wang} # HOGEに値がある場合はその値が展開される。HOGEが空の場合は、wangを標準エラー出力に書き出して exit 1 </code> ===== シェル変数の加工 ===== 指定位置で切り取り <code> x=abcdefg echo ${x:1:4} # => bcde </code> 変数の値の先頭・末尾でマッチした部分を削除する <code> x=hogehogefugafuga echo ${x#hoge} # => hogefugafuga 前方一致削除 echo ${x%fuga} # => hogehogefuga 後方一致削除 echo ${x#h*e} # => hogefugafuga * はワイルドカード echo ${x##h*e} # => fugafuga ##はワイルドカードを前方最長一致にする echo ${x%f*a} # => hogehogefuga * はワイルドカード echo ${x%%f*a} # => hogehoge %%はワイルドカードを後方最長一致にする </code> 文字列置換 <code> echo ${var/hoge/HOGE} # => HOGEhogefugafuga echo ${var//hoge/HOGE} # => HOGEHOGEfugafuga グローバルマッチ </code> 使用例:まとめてリネーム、拡張子まとめて変更 <code> $ ls a.txt b.txt c.txt $ for i in `ls`; do mv $i ${i%.txt}.php; done $ls a.php b.php c.php </code> ===== パラメータ展開 ===== 例 <code> HOGE="hoge.fuga.piyo" echo ${HOGE#*.} # 最短前方一致削除 => fuga.piyo echo ${HOGE##*.} # 最長前方一致削除 => piyo echo ${HOGE%.*} # 最短後方一致削除 => hoge.fuga echo ${HOGE%%.*} # 最長後方一致削除 => hoge </code> ファイル名から拡張子を削除したい場合は ''${filename%*.}''、拡張子だけ取り出したい場合は ''${filename##*.}'' ===== 何もしないコマンド ===== コロンは何もしないビルトインコマンド <code> : hogehoge # 何も起こらない </code> 変数HOGEが空だった場合、nyanを代入する <code> : ${HOGE:=nyan} </code> 変数HOGEが空だった場合、Error HOGE is emptyと出力して終了 <code> : ${HOGE:?"Error HOGE is empty"} </code> 可読性を考えると普通にifで書いた方がいいかも… <code> if [ -z "${HOGE}" ]; then echo "Error HOGE is empty" >&2 fi </code> ===== 標準入力がパイプ/リダイレクトされているか調べる ===== <code> test -p /dev/stdin </code> /dev/stdinが名前付きパイプである(=stdinがパイプで接続されている) <code> test -t 0 </code> ファイルディスクリプタ0番がterminalに紐づいている(=パイプやリダイレクトによるデータの入力がされていない) <code> if [ -t 0 ]; then # パイプやリダイレクトされてない # ./this_script elif [ -p /dev/stdin ]; then # シェルスクリプトが | で接続されている # cat hoge.txt | ./this_script else # 標準入力がリダイレクトされている # this_script < hoge.txt fi </code> ===== シェルスクリプトの引数 ===== ''$1'' ''$2'' で引数を取得できる。引数の数は ''$#'' で取得できる。引数の数が2桁になる場合は ''${10}'' のように {} で括る。 <code> # arg1.sh echo $# echo $1 echo $2 </code> <code> $ ./arg1.sh a b c d 4 a b </code> ''$@'' または ''$*'' でシェルスクリプトの引数全体を取得できる。 <code> # arg2.sh echo $@ echo $* </code> <code> $ ./arg2.sh 1 2 3 1 2 3 1 2 3 </code> ''$@'' と ''$*'' はダブルクオートで括った場合の動作が異なる。''"$@"''は''"1" "2" "3"''、''"$*"''は''"1 2 3"''と展開される。 ''$*'' は引数が一つの値にまとめられてしまう。ほとんどの場合、''$@'' の挙動が求められるので、''$@'' を使っておけば間違いない <code> # arg3.sh node -p -e 'process.argv.slice(1).join()' -- "$*" node -p -e 'process.argv.slice(1).length' -- "$*" node -p -e 'process.argv.slice(1).join()' -- "$@" node -p -e 'process.argv.slice(1).length' -- "$@" </code> <code> $ ./arg3.sh 1 2 3 1 2 3 1 1,2,3 3 </code> ''$*'' をダブルクオートで括った場合、空白スペースで結合される。結合文字は環境変数IFSで変更できるが影響範囲が大きいのであまり変えない方が良いだろう。 <code> # arg4.sh echo "$*" export IFS=":" echo "$*" </code> <code> $ ./arg4.sh 1 2 3 1 2 3 1:2:3 </code> これらの挙動はシェル関数の引数でも同様である。 ===== ヒアドキュメント ===== 変数に格納 <code shellscript> val=$(cat << 'EOS' hoge fuga piyo EOS ) </code> 標準入力に渡す <code shellscript> while read -r line do echo $line done << 'EOS' hoge fuga piyo EOS ) </code> 一度変数を経由する。''<<<''はヒアストリングと呼ばれるものでPOSIXには定義されておらずshでは使用できない。bashやzshで使用できる <code shellscript> val=$(cat << 'EOS' hoge fuga piyo EOS ) while read -r line do echo $line done <<< $val </code> クオートの有無は変数展開するかしないか <code shellscript> val='test' while read -r line do echo $line done << "EOF" ${val} ${val} ${val} EOF </code> クオートありの場合は変数展開されずに以下のように出力される <code> ${val} ${val} ${val} </code>
shellscript.txt
· 最終更新: 2024/08/20 15:31 by
nullpon
ページ用ツール
文書の表示
以前のリビジョン
バックリンク
文書の先頭へ