
シェルスクリプトの作法が ちょっと独特で、しょっちゅう上手く動かなくなるので 個人的によく使う書き方とかをメモ。
拡張子には.sh (ローカルルール)
foo.sh
ファイルの中身
頭におまじない
#!/bin/bash
コメント
# 以下はコメントになる
/* comment */は使えない
行終わり セミコロン
; 有ってもなくてもいい (phpでよく忘れる。phpはないとだめ)
一行で複数のコマンドを書くときは、 ; で区切って可
クオート 文字列 他の大概の言語と同じ(大して知らないけど)
" " ダブルクオート で 普通の文字列 変数は展開される
' ' シングルクオート で まんま文字列 変数は展開されない
(ただの変数には" " ダブルクオートを付けておいた方が吉)
バッククオート コマンドが実行された結果に置き換わる
result=`command`
以下は ls -la と同じことになる ls_result=$(ls) に似てる(後述)違いは謎(ぉぃ
option=-la
output=`ls $option`
echo $output
変数 シェルスクリプトは変数の型がないらしい。
変数の定義、代入 代入の際『=』の前後にスペースを入れてはダメらしい
hoge=111
呼び出し方 $をつけるらしい (ややこしい・・・・)
$hoge
しかも、基本的に文字列として扱われるらしいので、 (マジかょ・・・・)
num=1
num=$num + 1
echo $num
の結果が 『1 + 1』 という文字列になるらしい。 (勘弁してください・・・)
これを回避するには
let ++num
特殊な変数
シェルスクリプトに引数を渡すには(コマンドラインオプション)
foo.sh hoge fuga piyo
引数の参照
$1,$2,$3
スクリプト名の参照
$0
引数の数
$#
全ての引数を一度に参照する 違いは謎(ぉぃ
$* もしくは $@
シェルスクリプトのPID(プロセスID)
$$
最後に実行したコマンドのexit値
$?
上の例だと
$0 にはfoo.sh
$1 にはhoge
$2 にはfuga
$3 にはpiyo
$# には3
$* で hoge fuga piyo
$$ にはPIDの数字
$? は普通0か1
配列
配列の定義、代入
array[0]=hoge
array[1]=fuga
array[2]=piyo
もしくは
array=(hoge fuga piyo)
要素の追加
array=("${array[@]}" "hogera")
要素の一部を削除
unset array[1]
配列を削除
unset array
コマンドの実行結果が複数行ある時それをすべて配列に格納
ls_result=$(ls)
配列の参照 $は当然、{}が必須らしい。
${array[2]}
配列を全て参照 各要素を単語として
${array[@]}
配列を全て参照 IFS文字でつなげて一つの文字列で
IFS=";" Internal Field Separatorらしい よーわからん
echo "${array[*]}" " "がないとダメみたい
hoge;fuga;piyo
配列の要素数 #をつけて*を入れるらしい。
${#array[*]}
文字列結合 ただくっつける。『.』とか不用
str=$mojiretu1$mojiretu2
四則演算 exprが必要 演算子の前後にスペースも必要 演算子は普通
リダイレクト ファイルの入出力が驚くほど簡単
ファイルに上書き書き込み bar.txtにhogehogeと言う文字列を上書きで書き込み
echo "hogehoge" >bar.txt
ファイルに追加書き込み bar.txtにhogehogeと言う文字列を追記で書き込み(最終行)
echo "hogehoge" >>bar.txt
read LINE
ファイルから一行読み込み foo.txtから一行読み込んで$LINEに格納
read LINE <foo.txt
ファイルを1行ずつ処理
while read LINE
do [処理... $LINE]
done <foo.txt
ファイルの各行を配列に格納 とか
i=0
while read LINE
do array[$i]=$LINE
let ++i
done <foo.txt
パイプ
コマンドの出力をコマンドに入れる
command | command
/homeの.txtファイルのみを表示 とか
ls /home | grep "*.txt"
コマンドの出力を一行ずつ処理
command | while read LINE
do [処理... $LINE]
done
パイプの中はサブシェルでスコープが別⇒パイプの中の変数を外から参照できないらしい
サブシェルで動くというより別スレッドで動く挙動らしい なにその仕様・・・・
逆手に取ればマルチスレッド動作が簡単に??
制御文
if文 [ ]は本来はtestコマンドの略式らしい [ ]の文字の前後はスペースが必要
if [ 条件式 ]
then
[処理...]
elif [ 条件式 ]
then
[処理...]
else
[処理...]
fi
数値比較
if [ $num1 -eq $num2 ]
文字列比較
ファイル比較
特殊なオプション
一行if文
target=./hoge.txt
if [ -f $target ]; then rm -f $target ;fi
または
[ -f $target ] && rm -f $target
Like三項演算子(条件? 処理1:処理2;)
[ $hoge = $foo ] && echo "true" || echo "false"
if文の応用 らしい
testコマンドや[ ]の変わりに 他のコマンドを使って条件判定する
if echo $hoge | grep -sq "fuga"
then
~~~
grepは一致するパターンがあればそれを表示して戻り値に0(真)を返す
なければ戻り値に1(偽)を返す
ので、$hoge変数のなかにfugaの文字列があれば真、なければ偽になる
-sqはエラー出力と標準出力を抑制するgrepのオプション
for文
for str in ${array[@]}
do
echo $str
done
なにそのforeach・・・ orz
で、foreachは無いらしい。そらそうだ。
それでも、以下の方法でforっぽくできる らしい。
for (( i = 0; i < ${#array[@]}; ++i ))
do
echo ${array[$i]}
done
while文
i=1
while [ $i -le 5 ]
do
echo "$i"
let ++i
done
参考:
『Bashで覚えておくとよいデータ構造 - 配列Add Star』
『IFS てなに?』
『if 文と test コマンド』
『bash のアレコレ』
『bash,dash,zshのreadコマンドと「while read」のループ処理について』
『BASHでの変数について』
『bash 超プログラム術』
『Bash基礎文法最速マスター』
『簡素なif文は一行で書く』
『シェルスクリプト入門 [演算・比較]』
シェルスクリプトのデバッグ のヒント @IT
『シェルスクリプトの一部分をデバッグするには』
『シェルスクリプトをデバッグするには』
『シェルスクリプトの文法チェックを行うには』
拡張子には.sh (ローカルルール)
foo.sh
ファイルの中身
頭におまじない
#!/bin/bash
コメント
# 以下はコメントになる
/* comment */は使えない
行終わり セミコロン
; 有ってもなくてもいい (phpでよく忘れる。phpはないとだめ)
一行で複数のコマンドを書くときは、 ; で区切って可
クオート 文字列 他の大概の言語と同じ(大して知らないけど)
" " ダブルクオート で 普通の文字列 変数は展開される
' ' シングルクオート で まんま文字列 変数は展開されない
(ただの変数には" " ダブルクオートを付けておいた方が吉)
バッククオート コマンドが実行された結果に置き換わる
result=`command`
以下は ls -la と同じことになる ls_result=$(ls) に似てる(後述)違いは謎(ぉぃ
option=-la
output=`ls $option`
echo $output
ネストも可 内側のバッククオートにバックスラッシュ¥をつける
result=`command¥`command¥``
変数 シェルスクリプトは変数の型がないらしい。
変数の定義、代入 代入の際『=』の前後にスペースを入れてはダメらしい
hoge=111
呼び出し方 $をつけるらしい (ややこしい・・・・)
$hoge
しかも、基本的に文字列として扱われるらしいので、 (マジかょ・・・・)
num=1
num=$num + 1
echo $num
の結果が 『1 + 1』 という文字列になるらしい。 (勘弁してください・・・)
これを回避するには
num=1単純なインクリメンタル
let num="$num + 1"
echo $num →cf.四則演算
let ++num
特殊な変数
シェルスクリプトに引数を渡すには(コマンドラインオプション)
foo.sh hoge fuga piyo
引数の参照
$1,$2,$3
スクリプト名の参照
$0
引数の数
$#
全ての引数を一度に参照する 違いは謎(ぉぃ
$* もしくは $@
シェルスクリプトのPID(プロセスID)
$$
最後に実行したコマンドのexit値
$?
上の例だと
$0 にはfoo.sh
$1 にはhoge
$2 にはfuga
$3 にはpiyo
$# には3
$* で hoge fuga piyo
$$ にはPIDの数字
$? は普通0か1
配列
配列の定義、代入
array[0]=hoge
array[1]=fuga
array[2]=piyo
もしくは
array=(hoge fuga piyo)
要素の追加
array=("${array[@]}" "hogera")
要素の一部を削除
unset array[1]
配列を削除
unset array
コマンドの実行結果が複数行ある時それをすべて配列に格納
ls_result=$(ls)
配列の参照 $は当然、{}が必須らしい。
${array[2]}
配列を全て参照 各要素を単語として
${array[@]}
配列を全て参照 IFS文字でつなげて一つの文字列で
IFS=";" Internal Field Separatorらしい よーわからん
echo "${array[*]}" " "がないとダメみたい
hoge;fuga;piyo
配列の要素数 #をつけて*を入れるらしい。
${#array[*]}
文字列結合 ただくっつける。『.』とか不用
str=$mojiretu1$mojiretu2
四則演算 exprが必要 演算子の前後にスペースも必要 演算子は普通
a=`expr 5 + 3`
b=`expr 5 - 3`
c=`expr $a + $b`
d=`expr 5 ¥* 3` *はワイルドカードなのでバックスラッシュ¥が必要
e=`expr 5 / 3`
f=`expr 5 % 3`
リダイレクト ファイルの入出力が驚くほど簡単
ファイルに上書き書き込み bar.txtにhogehogeと言う文字列を上書きで書き込み
echo "hogehoge" >bar.txt
ファイルに追加書き込み bar.txtにhogehogeと言う文字列を追記で書き込み(最終行)
echo "hogehoge" >>bar.txt
echoでタブ、改行を表現する方法 -e オプションをつけるキーボードからの入力 キーボードの入力を待って、Enterまでの入力を$LINEに格納
echo -e "hello¥tworld¥nhello¥nworld"
read LINE
ファイルから一行読み込み foo.txtから一行読み込んで$LINEに格納
read LINE <foo.txt
ファイルを1行ずつ処理
while read LINE
do [処理... $LINE]
done <foo.txt
ファイルの各行を配列に格納 とか
i=0
while read LINE
do array[$i]=$LINE
let ++i
done <foo.txt
パイプ
コマンドの出力をコマンドに入れる
command | command
/homeの.txtファイルのみを表示 とか
ls /home | grep "*.txt"
コマンドの出力を一行ずつ処理
command | while read LINE
do [処理... $LINE]
done
パイプの中はサブシェルでスコープが別⇒パイプの中の変数を外から参照できないらしい
サブシェルで動くというより別スレッドで動く挙動らしい なにその仕様・・・・
逆手に取ればマルチスレッド動作が簡単に??
制御文
if文 [ ]は本来はtestコマンドの略式らしい [ ]の文字の前後はスペースが必要
if [ 条件式 ]
then
[処理...]
elif [ 条件式 ]
then
[処理...]
else
[処理...]
fi
数値比較
if [ $num1 -eq $num2 ]
演算子 | 意味 | |
-eq | == | equal |
-ne | != | not equal |
-lt | < | less than |
-le | <= | less equal |
-gt | > | greater than |
-ge | >= | greater equal |
演算子 | 意味 |
= | == |
!= | != |
=~ | 左辺の文字列に右辺のパターンによる部分文字列が含まれるか |
!~ | 左辺の文字列に右辺のパターンによる部分文字列以外が含まれるか |
演算子 | 意味 | |
-nt | より新しい | newer than |
-ot | より古い | older than |
オプション | 使い方 | 意味 |
-z | [ -z string ] | string の文字列長が 0 ならば真 |
-n | [ -n string ] | string の文字列長が 0 より大ならば真 |
-d | [ -d file ] | file がディレクトリならば真 |
-e | [ -e file ] | file が存在するならば真 |
-f | [ -f file ] | file が普通のファイルならば真 |
-s | [ -s file ] | file が 0 より大きいサイズならば真 |
-r | [ -r file ] | file が読み取り可能ならば真 |
-w | [ -w file ] | file が書き込み可能ならば真 |
-x | [ -x file ] | file が実行可能ならば真 |
-O | [ -O file ] | file の所有者ならば真 |
-G | [ -G file ] | file の所有者と同じグループに属するならば真 |
一行if文
target=./hoge.txt
if [ -f $target ]; then rm -f $target ;fi
または
[ -f $target ] && rm -f $target
Like三項演算子(条件? 処理1:処理2;)
[ $hoge = $foo ] && echo "true" || echo "false"
if文の応用 らしい
testコマンドや[ ]の変わりに 他のコマンドを使って条件判定する
if echo $hoge | grep -sq "fuga"
then
~~~
grepは一致するパターンがあればそれを表示して戻り値に0(真)を返す
なければ戻り値に1(偽)を返す
ので、$hoge変数のなかにfugaの文字列があれば真、なければ偽になる
-sqはエラー出力と標準出力を抑制するgrepのオプション
for文
for str in ${array[@]}
do
echo $str
done
なにそのforeach・・・ orz
で、foreachは無いらしい。そらそうだ。
それでも、以下の方法でforっぽくできる らしい。
for (( i = 0; i < ${#array[@]}; ++i ))
do
echo ${array[$i]}
done
while文
i=1
while [ $i -le 5 ]
do
echo "$i"
let ++i
done
参考:
『Bashで覚えておくとよいデータ構造 - 配列Add Star』
『IFS てなに?』
『if 文と test コマンド』
『bash のアレコレ』
『bash,dash,zshのreadコマンドと「while read」のループ処理について』
『BASHでの変数について』
『bash 超プログラム術』
『Bash基礎文法最速マスター』
『簡素なif文は一行で書く』
『シェルスクリプト入門 [演算・比較]』
シェルスクリプトのデバッグ のヒント @IT
『シェルスクリプトの一部分をデバッグするには』
『シェルスクリプトをデバッグするには』
『シェルスクリプトの文法チェックを行うには』
スポンサーサイト


