#author("2019-01-31T15:43:35+00:00","default:haikikyou","haikikyou")
#contents
* パラメータ展開 [#mf070ac4]
*** ${parameter} [#lc33dd13]
parameterの値に置換される。
#geshi(bash){{{
#!/usr/bin/env bash
PARAM="parameter"
echo $PARAM #=> parameter
}}}
*** ${parameter:-word} [#r6cf08cd]
parameter が設定されていないか空文字列であれば、 wordを展開したものに置換される。そうでなければ、 parameter の値に置換される。
変数のデフォルト値を設定したい場合などによく使う。
#geshi(bash){{{
echo $USER #=> "moritetu"
# ${parameter:-word}
SSH_USER="${USER:-"guest"}"
echo "$SSH_USER" #=> "moritetu"
SSH_OPTS="${OPTIONS:-""}"
echo "$SSH_OPTS" #=> ""
}}}
*** ${parameter:=word} [#h57e3e86]
parameterが設定されていないか空文字列であれば、 wordを展開したものがparameter に代入される。その後、parameter の値への置換が行われる。
#geshi(bash){{{
# ${parameter:=word}
# ex1
${COMMAND:="date"} #=> 2019年 1月30日 水曜日 22時10分22秒 JST
# ex2
: ${PARAM:="param1"}
echo $PARAM #=> param1
}}}
*** ${parameter:?word} [#v638fa90]
- parameterが空文字列または設定されていない場合、word を展開したものが標準エラー出力に出力される。
- wordがなければ パラメータが空文字列または設定されていないことを示すメッセージが標準エラー出力に出力される。
- 対話的シェルでなければ、 シェルは終了する。
- parameterに空文字列以外が設定されていれば、 parameter 値への置換が行われる。
#geshi(bash){{{
# ${parameter:?word}
# ex1
${not_defined_param:?} #=> not_defined_param: パラメータが null または設定されていません
# シェルは終了する
# ex2
${not_defined_param2:?"parameter is not defined"} #=> not_defined_param2: parameter is not defined
# シェルは終了する
# ex3
defined_param2="defined_param2"
echo ${defined_param2:?"parameter is not defined"} #=> defined_param2
}}}
*** ${parameter:+word} [#g28240aa]
parameter が空文字列または設定されていなければ、空文字列に置換される。そうでなければ word を展開したものに置換される。${parameter:-word} の逆。
#geshi(bash){{{
# ${parameter:+word}
echo ${parameter:+"word"} #=> ""
parameter="defined"
echo ${parameter:+"word"} #=> word
}}}
*** ${parameter:offset}、${parameter:offset:length} [#v6387b01]
部分文字列の展開を行なう。length指定がある場合は、parameter を展開したものから最大 length 文字を取り出す。length指定がない場合は、指定したインデックスから末尾までの文字を取り出す。配列の場合は、指定したインデックスからlengthで指定される要素を取り出す。
#geshi(bash){{{
# ${parameter:offset}
parameter="012345" #=>
array=(0 1 2 3 4 5) #=>
echo ${parameter:2} #=> 2345
echo ${parameter:-1} #=> 012345
echo ${parameter:-2} #=> 012345
echo ${array[@]:-2} #=> 0 1 2 3 4 5
echo ${array[@]:2} #=> 2 3 4 5
echo ${parameter:2:2} #=> 23
echo ${parameter:2:-1} #=> 234
echo ${array[@]:2:1} #=> 2
echo ${array[@]:2:-1} #=> parameter.sh: 行 8: -1: substring expression < 0
}}}
*** ${!prefix*}、${!prefix@} [#jd3445b4]
prefix で始まる全ての変数の名前に展開して、 IFS 特殊変数の最初の文字によって区切る。
#geshi(bash){{{
# ${!prefix*}
parameter_1="p1" #=>
parameter_2="p2" #=>
echo ${!param*} #=> parameter_1 parameter_2
(IFS="_|" ; echo ${!param*}) #=> parameter 1 parameter 2
# ${!prefix@}
parameter_1="p1" #=>
parameter_2="p2" #=>
echo ${!param@} #=> parameter_1 parameter_2
for p in "${!param@}"; do eval echo \$$p; done #=> p1
p2
}}}
*** ${!name[*]}、${!name[@]} [#vf3ba1d3]
配列のキーのリストに展開される。ハッシュの場合は、キーを取り出すことができる。配列の場合は、インデックスとなる。*と@の違いは、ダブルクォートで囲まれた場合の展開方法が異なる。
#geshi(bash){{{
array=(a b c d e f) #=>
# ${!name[*]}
echo ${!array[*]} #=> 0 1 2 3 4 5
# ${!name[@]}
echo ${!array[@]} #=> 0 1 2 3 4 5
# ハッシュ定義
declare -g -A map #=>
map=(["a"]=0 ["b"]=1 ["c"]=2 ["d"]=3 ["e"]=4 ["f"]=5) #=>
echo ${!map[*]} #=> a b c d e f
echo ${map[@]} #=> 0 1 2 3 4 5
echo ${!map[@]} #=> a b c d e f
}}}
*** ${#parameter} [#h4f5448b]
パラメータの長さを示す。文字列の場合は文字列の長さ、配列の場合は要素数。
#geshi(bash){{{
# ${$parameter}
strings="12345" #=>
echo ${#strings} #=> 5
strings="あいう" #=>
echo ${#strings} #=> 3
array=(0 1 2 3 4 5) #=>
echo ${#array} #=> 1
echo ${#array[@]} #=> 6
}}}
*** ${parameter#word}、${parameter##word} [#y841fdc6]
#geshi(bash){{{
}}}
*** ${parameter%word}、${parameter%%word} [#tf4bc178]
#geshi(bash){{{
}}}
*** ${parameter/pattern/string} [#i4603bba]
#geshi(bash){{{
}}}
*** ${parameter^pattern}、${parameter^^pattern} [#de760312]
#geshi(bash){{{
}}}
*** ${parameter,pattern}、${parameter,,pattern} [#r736607f]
#geshi(bash){{{
}}}
* プロセス置換 [#we760055]
- &code(){>(list)};は、ファイルへの出力がlistへの入力となる。
- &code(){<(list)};は、listの出力がファイルへの入力となる。
&label(sample){サンプル}; ''lsの結果で*.shファイルのみを出力''
#geshi(bash,number){{{
a=
while IFS= read -r line
do
a="$line:$a"
done < <(ls . | grep -e "\.sh$")
}}}
&label(sample){サンプル}; ''a.txtとb.txtをdiffの入力ファイルとして比較''
#geshi(bash,number){{{
diff -u <(cat a.txt) <(cat b.txt)
}}}
&label(sample){サンプル};
#geshi(bash,number){{{
exec 3>&1
exec > >(while read line; do echo "$(date): $line";done)
echo "hello"
echo "bar"
exec 1>&3 3>&-
}}}
* execを使った入出力のリダイレクト [#s12f0ef4]
execコマンドでリダイレクトだけを指定すると、シェル自身のファイル記述子とデバイスの対応を変更することができる。
**** &label(sample){例}; execを使った入力のリダイレクト [#z15e5164]
#geshi(bash,number){{{
# copy stdin to descriptor 3
exec 3<&0
# redirect stdin to test.c
exec < test.c
# read a line from test.c
read line
echo $line
# restore stdin and close descriptor 3
exec 0<&3 3<&-
}}}
**** &label(sample){例}; execを使った出力のリダイレクト [#z15e5164]
#geshi(bash,number){{{
# save stdout as descriptor 3
exec 3>&1
exec > test.txt
echo "this message is written into the test.txt"
# restore stdout and close descriptor 3
exec 1>&3 3>&-
}}}
特定の式や文の出力をまとめてリダイレクトしたい場合は、ブレースを使った複合コマンドでも処理できる。
&label(sample){例}; ''複合コマンドの出力をファイルにリダイレクトする''
#geshi(bash,number){{{
#!/usr/bin/env bash
# 複合コマンド
{
# stdout.txtに出力
echo "this message is written into stdout.txt"
# stderr.txtに出力
echo "this message is written into stderr.txt" >&2
} > stdout.txt 2> stderr.txt
}}}
* 参考リンク [#q8d32fb3]
- [[Advanced Bash-Scripting Guid>http://tldp.org/LDP/abs/html/index.html]] - &size(11){&color(gray){on http://tldp.org/LDP/abs/html/index.html};};
- [[Man page of BASH>https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html]] - &size(11){&color(gray){on https://linuxjm.osdn.jp/html/GNU_bash/man1/bash.1.html};};
- テストフレームワーク
-- [[Bats>https://github.com/sstephenson/bats]] - &size(11){&color(gray){on https://github.com/sstephenson/bats};};
-- [[shunit2>https://github.com/kward/shunit2]] - &size(11){&color(gray){on https://github.com/kward/shunit2};};
--- [[Pac Learner shUnit2 2.1.x ドキュメント>https://sites.google.com/site/paclearner/shunit2-documentation]] - &size(11){&color(gray){on https://sites.google.com/site/paclearner/shunit2-documentation};};
-- [[Baut (Bash Unittest Tool)>https://github.com/moritetu/baut]] - - &size(11){&color(gray){on https://github.com/moritetu/baut};};