最終更新:2017-02-17 (金) 16:38:09 (2623d)  

シェルスクリプト
Top / シェルスクリプト

http://www.linux.or.jp/JM/html/GNU_bash/man1/bash.1.html

基本

先頭に

#!/bin/sh

と書く

予約語

 ! case do done elif else esac fi for function if in select then until while { } time [[ ]]  

コメント

#ほげほげ

シェルスクリプト/変数

シェル変数

  • 変数に値を代入するには「変数名=値」とします。「=」の前後にはスペースやタブを入れることはできません。
  • 変数を参照する場合は、変数名の前に「$」を付けます。
    var="ほげほげ"
    echo $var
  • 変数参照時に変数が誤解釈されそうな場合には「""」または「{ }」で変数名を囲む。
    var2=${var1}0

変数の展開など

  • 引用符
    記号意味
    '...'内部の文字列をそのままの文字列として返す.
    "..."内部に含まれる変数等 $,`...`,\ を解釈した結果の文字列を返す
    `...`内部にあるコマンド(群)を実行し, その標準出力を文字列として返す.

引数

  • 受け取った引数は、$1から$9という変数に格納される
     echo $1

特殊な変数

  • 特殊変数一覧 (シェルスクリプト/変数)
    変数意味
    $$シェル自身のPID(プロセスID)
    $!?シェルが最後に実行したバックグラウンドプロセスのPID
    $?最後に実行したコマンドの終了コード(戻り値)
    $-?setコマンドを使って設定したフラグの一覧
    $*全引数リスト。"$*"のように「"」で囲んだ場合、"$1 $2 … $n" と全引数を一つにくっついた形で展開される。
    $@全引数リスト。"$@"のように「"」で囲んだ場合、"$1" "$2" … "$n" とそれぞれの引数を個別にダブルクォートで囲んで展開される。
    $♯?シェルに与えられた引数の個数
    $0シェル自身のファイル名
    $1~$nシェルに与えられた引数の値。$1は第1引数、$2は第2引数…となる。

未設定変数など

  • 空かどうか
    書式変数が空でないとき変数が空のとき
    ${変数 :-word }変数 の値が使われるword の値が使われる
    ${変数 :=word }変数 の値が使われるword の値が変数に代入されて使われる
    ${変数 :?word }変数 の値が使われるword がエラーメッセージとして使われ、スクリプトが終了する
    ${変数 :+word }word が変数 に代入される何もしない
  • 定義済みかどうか
    書式変数が定義されているとき変数が定義されていないとき
    ${変数 -word }変数 の値が使われるword の値が使われる
    ${変数 =word }変数 の値が使われるword の値が変数に代入されて使われる
    ${変数 ?word }変数 の値が使われるword がエラーメッセージとして使われ、スクリプトが終了する
    ${変数 +word }word が変数 に代入される何もしない

文字列演算子

  • オフセットとか
    使い方意味目的
    ${varname:offset} ${varname:offset:length}サブ文字列を展開する. offsetの位置からlength文字 の長さのサブ文字列を$varnameの値から取り出す. 文字の位置は0からカウントする. lengthが省略された場合, offsetの位置から $varnameの終りまでのサブ文字列が返される. offsetが0より小さかった場合, 開始位置は $varnameのおわりからカウントされる. varnameが@の場合, lengthはoffsetを先頭とする 位置パラメータの番号になる.文字の一部を返す(サブ文字列またはスライスという).countがfrogfootmanと設定されている場合, ${count:4}はfootmanを返し, ${count:4:4}はfootを返す.
    ${#varname}$varnameの文字数(全角文字も1文字)になる
    ${varname#接頭辞}$varnameから一致する最小部分の接頭辞を削除したもの
    ${varname##接頭辞}$varnameから一致する最大部分の接頭辞を削除したもの
    ${varname%接尾辞}$varnameから一致する最小部分の接尾辞を削除したもの
    ${varname%%接尾辞}$varnameから一致する最大部分の接尾辞を削除したもの

配列

  • 配列を扱うことも出来る
     NAME[0]=value
     NAME=(value1 value2 …)
    指定方法説明
    ${NAME[n]}指定された要素の内容。
    ${NAME}${NAME[0]}と同じ。
    ${NAME[*]}配列内の全要素。
    ${NAME[@]}
    ${#NAME[n]}指定された要素の文字数。
    ${#NAME}${#NAME[0]}と同じ。
    ${#NAME[*]}配列の要素数。
    ${#NAME[@]}

ワイルドカード

  • * , ? , [ , ] の各特殊文字はワイルドカードと呼ばれ,任意のコマンド中でファイル名を指定するときに利用できる
  • シェルはそのパターンにマッチしたファイル名を探して、 自動的に完全なファイル名に直してコマンドを実行してくれる
    ワイルドカード意味
    *任意(0文字以上)の文字列
    ?任意の1文字
    [ ]中に指定されたうちの一文字
    [! ]の中に指定された文字以外の一文字
    {文字列1,文字列2,...}文字列1あるいは文字列2あるいは...というように可能性の ある文字列をいくつか列挙する
  • *はカレントディレクトリの全ファイルに置き換わる

コマンドシーケンス

  • コマンドの慣用句説明
    command &command をサブシェル中でバックグラウンド実行
    command1 | command2command1 の標準出力を command2 の標準入力に パイプ (同時並行で実行)
    command1 2>&1 | command2command1 の標準出力と標準エラー出力を command2 の標準入力にパイプ (同時進行で実行)
    command1 ; command2command1 を実行し、後に続いて command2 を実行
    command1 && command2command1 を実行; もし成功したら、 後に続いて command2 を実行 (command1 と command2 の両方が成功したら、正常終了を返す)
    command1 || command2command1 を実行; もし成功しなかったら、後に続いて command2 を実行 (command1 か command2 のどちらかが成功したら、正常終了を返す)
    command > foocommand の標準出力を foo ファイルにリダイレクト (上書き)
    command 2> foocommand の標準エラー出力を foo ファイルにリダイレクト (上書き)
    command >> foocommand の標準出力を foo ファイルにリダイレクト (追記)
    command 2>> foocommand の標準エラー出力を foo ファイルにリダイレクト (追記)
    command > foo 2>&1command の標準出力と標準エラー出力を foo ファイルにリダイレクト
    command < foocommand の標準入力を foo ファイルからリダイレクト
    command << delimitercommand の標準入力を "delimiter" に出会うまでのこれに続く行からリダイレクト (ヒアドキュメント?)
    command <<- delimitercommand の標準入力を "delimiter" に出会うまでのこれに続く行からリダイレクト (ヒアドキュメント?、行頭のタブ文字は入力から削除)

演算

  • exprコマンドを使う
    #!/bin/sh
    A=1
    B=2
    C=`expr ${A} + ${B}`
    echo ${C} #3と表示
    #!/bin/sh
    A=1
    B=2
    C=`expr ${A}+${B}` #スペースで区切らないと
    echo ${C} #1+2と表示される
  • exprの演算子
    演算子意味
    a + baとbの和
    a - baとbの差
    a \* baとbの積
    a / baとbの商
    a % baとbの剰余
  • 乗算の演算子は「*」ですが、UNIXでは「*」はワイルドカードという特別な意味がありますので、エスケープ文字「\」を使用して「\*」と書く
  • 演算子の前後のスペースは省略できない

論理結合

  • if文やwhile文で、複数の条件を結合(AND,OR)して評価したい場合は、以下のように記述します。
    論理結合演算子意味
    ! 条件条件が偽であれば真
    条件1 -a 条件2条件1が真、かつ、条件2が真であれば真
    条件1 -o 条件2条件1が真、または、条件2が真であれば真

制御構文

if文

  • if 条件1 
    then
      処理1
    elif 条件2
    then
      処理2
    else
      処理3
    fi
    if [ $hoge = $fuga ]; then
      echo "文字列は同じです"
    else
      echo "文字列は違います"
    fi
if cat $file >/dev/null; then echo here; else echo absent; fi
if cat $file >/dev/null
then
    echo here
else 
    echo absent
fi

[ ]構文

  • 内部組み込みコマンド(同内容の外部コマンドも /usr/bin/test? にある)「test」の判定と同じ
    #!/bin/sh
    
    #ファイルが存在すれば削除
    
    TEST_FILE=/home/hoge/test.txt
    if [ -e ${TEST_FILE} ] 
    then
        rm ${TEST_FILE}
        echo "removed "${TEST_FILE}
    else
        echo ${TEST_FILE}" is not existed."
    fi
     
  • 数値比較
    表現真($? == 0)を返す場合
    num1 -eq num2num1 = num2
    num1 -ne num2num1 != num2
    num1 -gt num2num1 > num2
    num1 -ge num2num1 >= num2
    num1 -lt num2num1 < num2
    num1 -le num2num1 <= num2
  • 文字列比較
    表現真($? == 0)を返す場合
    str1 = str2文字列の一致
    str1 != str2文字列の不一致
    -n str文字列が空ではない
    -z str文字列が空である
    str1 -gt str2数値表現として、str1 > str2
    str1 -ge str2数値表現として、str1 >= str2
    str1 -lt str2数値表現として、str1 < str2
    str1 -le str2数値表現として、str1 <= str2
    !結果の真偽を逆転する
  • ファイルに対する処理
    表現真($? == 0)を返す場合
    -d fileファイル名がディレクトリである
    -e fileファイル名が存在する
    -f fileファイル名が通常ファイルである
    -r fileファイル名がパーミッションの上で読むことができる
    -s fileファイル名が存在し、かつ空ではない
    -w fileファイル名がパーミッションの上で書き込むことができる
    -x fileファイル名がパーミッションの上で実行可能である
    -O fileそのファイルの所有者である
    -G fileそのファイルの所有者と同じグループに属する
    file1 -nt file2更新時間を比較し、file1 の方が新しい
    file1 -ot file2更新時間を比較し、file1 の方が古い

for文

  • 基本
    for 変数 in 値リスト
    do
      処理
    done
  • for i in 1 2 3 4 5
    do
        echo $i
    done
  • 基本2
    for (( 初期化 ; 継続条件 ; 再初期化 ))
    do
      変数を使用する処理
    done
  • コマンドの実行結果を値リストに指定する
    for var in `コマンド`
    do
      処理
    done
    • #for var in `ls -1`と同じ処理?
      # in に続くリストがワイルドカード展開されて、カレントディレクトリのすべてのファイルになる
      for file in *
      do
         if [ -d $file ]; then ls -d $file; fi
      done
      #!bin/sh
      for srcname in `find /home/hoge/programming/c | egrep '.+\.c$'`;do
          case `basename $srcname` in
              a.c | b.c | c.c) ;; # exclude
      	*)
      	    # C言語のソースファイルに何かする
          esac
      done

case文

  • case 変数 in
       パターン1) 処理;;
       パターン2) 処理;;
       パターン3 | パターン4) 処理;;
       *) 処理;;
    esac
  • ;;は「case文を抜ける」という意味
  • *)は「いずれのパターンにもあてはまらない場合」という意味で、省略可能
  • パターンを「 | 」で区切って論理和(or)をとることも可能
  • パターンには正規表現が使える
    case "$var" in
      a* ) echo "aで始まる文字列" ;;
      ?b* ) echo "2文字目がbの文字列" ;;
      [A-Z]* ) echo "大文字で始まる文字列" ;;
      [!xX]* ) echo "先頭がxではない文字列" ;;
      * ) echo "上記のいずれでもない文字列" ;;
    esac

while文

until文

select文

  • メニューを表示してユーザに選択を促す(プロンプトが表示される)ようなスクリプトの記述ができる
    select 変数 in リスト
    do
            内容
    done
    select 変数 in リスト; do
            内容
    done

テキスト処理

制御構文whileやforを避ける方法

関連

参考