Tag: Bash

目次

参考情報

規約に関して

変数名の規約

  • ローカル変数: 小文字、グローバル変数: 大文字、エクスポートする変数: 大文字。
  • インデントはスペース4個。
  • readonlyはできれば使う。exportと併用する場合、readonlyで定義してそのあとexportすれば良い。
  • ファイル名の名前だけFOO_FILENAME、フルパスFOO_FILE。ディレクトリ名の名前だけFOO_DIRNAME、フルパスFOO_DIR

デフォルトオプション

  • かならずset -euする。set -eでエラーで止まる。set -uで未定義変数でエラー。Bash - シェルスクリプトを書くときはset -euしておく - Qiita
  • set -uするとコマンドライン引数が指定されなかったときに、$1がエラーになる。これを防ぐためにはデフォルト値を使う。
    TASKNAME=${1:-abc}
  • set -xするとコマンドが標準出力される

パラメータ

$0コマンド名
$11つ目の引数
$22つ目の引数
$*残りの引数全部
$#引数の個数

変数

参考

基本

  • 小文字でも大文字でも良い。
  • 宣言時は$を頭につけない。両端にスペースをいれない。
  • 参照時は$を頭につける。厳密に使いたい時は変数名を{}で囲う必要もある。
    a="XYZ"
    echo "$a"
    echo "${a}"
    
  • 空白がはいった変数のことを考えると、変数使用時常にダブルクォートで囲ったほうが安全かも。if文でエラーにならないように。

環境変数とシェル変数

環境変数

  • export FOOのようにexportされた変数が環境変数と呼ばれる。
  • printenv FOOで確認できる。
  • 親シェルでexportされた変数は小シェルに引き継がれる。子で引き継がれた変数を変更しても親には影響しない。
  • export済み変数を設定する場合再度exportする必要はない。例えばexport済みのLANGを変更する場合以下でOK。
    LANG="hoge"

シェル変数

  • そのスクリプトか、または現プロンプト上でしかアクセスが有効でない。
  • シェルスクリプトでローカル変数として使えるほか、bashのPS1のような変数にも使われている。
  • set PS1のように確認できる。
  • set で全部表示できる。

デフォルト値

  • ${var:-デフォルト値}で設定できる。
    var="a b c"
    str=${var:-"d e f"}
    echo $str
    str=${var2:-"d e f"}
    echo $str
    
  • 以下が出力される
    a b c
    d e f
    
  • コマンド引数
  • 以下のシェルスクリプト default.sh を考える。
    arg1=${1:-"xxx"}
    echo $arg1
    
  • そのまま実行すると、xxxが出力される。「./default.sh yyy」と実行するとyyyが出力される。

制御構造

if then else

空白チェックする

  • 直接""と比較するのが簡単か
        str=$1
        if [ "$str" = "" ]; then
            echo "empty"
        else
            echo "not empty"
        fi
    

ファイルの存在チェック

  • "-f"を使用する
    if [ -f $file ]; then
        echo "$file is file."
    else
        echo "$file is not file."
    fi
    
  • びっくりマークで否定
    if [ ! -f $file ]; then
        echo "$file is not file."
    else
        echo "$file is file."
    fi
    

exit

関数

パラメータの基本

  • $1,$2のように格納される。そのまま使ってもいいし変数に代入してもよい(厳密にはstrとするとグローバル変数になるのでローカルにしたほうがよい)。
    function test()
    {
        str=$1
        echo "$str"
    }
    
    test a
    

パラメータの存在チェック

  • 以下のようなスクリプトを考える。
    function check()
    {
        str=$1
        if [ "$str" = "" ]; then
            echo "empty"
        else
            echo "not empty"
        fi
    }
    
    echo "\$0=$0"
    check $0
    
    echo "\$1=$1"
    check $1
    
    echo "\$2=$2"
    check $2
    
  • ./param.shとして実行すると以下の結果が表示される。
    $0=./param.sh
    not empty
    $1=
    empty
    $2=
    empty
    

パラメータとして配列を含む引数を渡したい

shift併用型

  • 最初の引数とそれ以外の配列引数に分ける。Passing arrays as parameters in bash - Stack Overflow
    calling_function()
    {
        variable="a"
        array=( "x", "y", "z" )
        called_function "${variable}" "${array[@]}"
    }
    
    called_function()
    {
        local_variable="${1}"
        shift
        local_array=("${@}")
    }
    

動的スコープでそのまま参照

コマンド置換

バッククォート`command`または$(command)を使う

Tips

.bash_profile vs .bashrc

  • 通常はログイン時に.bash_profile、シェル起動時に.bashrcらしい
  • OS XでGUIからターミナルを開いたときは、.bash_profileしか読み込まれない(X11からターミナルを開く場合は.bashrcが読まれるらしいので挙動が違う)。
  • そこで、.bash_profileから.bashrcを読み込むように設定しておく。
    # read .bashrc                                                                  
    if [ -f ~/.bashrc ]; then
    . ~/.bashrc
    fi
    

スクリプトの存在するディレクトリを取得したい

  • スクリプト内から他のスクリプトを呼び出したい場合など、スクリプトが存在するディレクトリが必要になる場合がある。
    export BASE_DIR=$(cd $(dirname $0);pwd)

複雑なプログラムを作成したい

  • オープンソースを参考にする。
  • Linuxの/etc/network-scriptsとか、tomcatの起動スクリプトとか。

実行したプログラムをエコーしたい

OSを判定したい

  • zshとVimでOS判定 - shkh's blogにあるように$OSTYPEが使える。
  • バージョン番号が付いていたりそのたプリフィックスが付属していることがあるので、末尾のアスタリスクを忘れないように。
    case ${OSTYPE} in
        darwin*)
            #ここにMac向けの設定
            ;;
        linux*)
            #ここにLinux向けの設定
            ;;
    esac
    

パラメータの個数をチェックする

  • 例えばパラメータ無しの場合とパラメータありの場合で処理を変更したい場合
    function check()
    {
        str=$1
        if [ "$str" = "" ]; then
            echo "引数なし"
        else
            echo "引数あり"
        fi
    }
    

空白を含むファイル名を正しく渡したい

  • 例えばシェルスクリプトから、rubyスクリプトを呼び出したい場合単にバックスラッシュでエスケープして渡しただけだと、分割したファイル名として扱われる
    #!/bin/sh
    ruby test.rb $@
  • この場合全体をエスケープしてやればよい。Accessing bash command line args $@ vs $* - Stack Overflow
    ruby test.rb "$@"

チルダの展開

トラブルシューティング

echo -nがきかない

"$@" != ""がエラーになる

  • シェルスクリプトでの$@の罠に書いてあること。
  • 以下のスクリプトを実行するとき、「./atmark.sh a」はいいけど、引数なしor2個以上の引数でエラーとなる。
    #!/usr/bin/env bash
    if [ "$@" != "" ];then
      echo "$@"
    else
      echo empty
    fi
    
  • これは"$@"が次のように展開されるため。
    "$1" "$2" "$3"
  • つまり、if [ "$@" = "" ];thenが、if [ "" = "" ];thenとなったりするため。

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-02-21 (水) 14:03:54 (480d)