展開

ブレース展開

{x..y[..incr]}
  • {} を使って行なう。ブレース展開を使うと、値の組み合わせのパターン生成に便利な手法。
  • 他の展開よりも先に行われるので、変数展開を期待して埋め込んでも意図した結果にならないだろう。
  • { や , はバックスラッシュでエスケープできる。
param=10                        #=> 

echo `seq 1 10`                 #=> 1 2 3 4 5 6 7 8 9 10
echo {1..10..1}                 #=> 1 2 3 4 5 6 7 8 9 10
echo {1..10..3}                 #=> 1 4 7 10
echo {1..10}                    #=> 1 2 3 4 5 6 7 8 9 10
echo {10..1..-1}                #=> 10 9 8 7 6 5 4 3 2 1
echo {10..-1}                   #=> 10 9 8 7 6 5 4 3 2 1 0 -1
echo {10..10..-1}               #=> 10
echo {1..$param}                #=> {1..10}
eval echo {1..$param}           #=> 1 2 3 4 5 6 7 8 9 10

echo test{1,}                   #=> test1 test
echo test{1,2,3}                #=> test1 test2 test3
echo test{,}                    #=> test test
echo test{{,}}                  #=> test{} test{}
echo {postgresql,pg_hba}.conf   #=> postgresql.conf pg_hba.conf

パラメータ展開

${parameter}

parameterの値に置換される。

#!/usr/bin/env bash
PARAM="parameter"
echo $PARAM  #=> parameter

${parameter:-word}

parameter が設定されていないか空文字列であれば、 wordを展開したものに置換される。そうでなければ、 parameter の値に置換される。

変数のデフォルト値を設定したい場合などによく使う。

echo $USER #=> "moritetu"

# ${parameter:-word}
SSH_USER="${USER:-"guest"}"                                                                                                                                          
echo "$SSH_USER" #=> "moritetu"

SSH_OPTS="${OPTIONS:-""}"                                                                                                                                            
echo "$SSH_OPTS"  #=> ""

${parameter:=word}

parameterが設定されていないか空文字列であれば、 wordを展開したものがparameter に代入される。その後、parameter の値への置換が行われる。

# ${parameter:=word}

# ex1
${COMMAND:="date"} #=> 2019年 1月30日 水曜日 22時10分22秒 JST

# ex2
: ${PARAM:="param1"}
echo $PARAM #=> param1

${parameter:?word}

  • parameterが空文字列または設定されていない場合、word を展開したものが標準エラー出力に出力される。
  • wordがなければ パラメータが空文字列または設定されていないことを示すメッセージが標準エラー出力に出力される。
  • 対話的シェルでなければ、 シェルは終了する。
  • parameterに空文字列以外が設定されていれば、 parameter 値への置換が行われる。
# ${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}

parameter が空文字列または設定されていなければ、空文字列に置換される。そうでなければ word を展開したものに置換される。${parameter:-word} の逆。

# ${parameter:+word}

echo ${parameter:+"word"} #=> ""

parameter="defined"
echo ${parameter:+"word"} #=> word

${parameter:offset}、${parameter:offset:length}

  • 部分文字列の展開を行なう。
  • length指定がある場合は、parameter を展開したものから最大 length 文字を取り出す。length指定がない場合は、指定したインデックスから末尾までの文字を取り出す。
  • 配列の場合は、指定したインデックスからlengthで指定される要素を取り出す。
# ${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@}

prefix で始まる全ての変数の名前に展開して、 IFS 特殊変数の最初の文字によって区切る。

# ${!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[@]}

  • 配列のキーのリストに展開される。ハッシュの場合は、キーを取り出すことができる。
  • 配列の場合は、インデックスとなる。*と@の違いは、ダブルクォートで囲まれた場合の展開方法が異なる。
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}

パラメータの長さを示す。文字列の場合は文字列の長さ、配列の場合は要素数。

# ${$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}

  • parameterに対しwordで前方一致するパターンを取り除いた結果を返す。#は最短一致、##は最長一致のパターン。
  • parameterが@や*の配列変数の場合、全ての要素に対して順番に適用される。
parameter="test.sh.j2"          #=> 
array=(index.html.erb hello.html.erb)  #=> 

# ${parameter#word}
echo ${parameter#*.}            #=> sh.j2
echo ${array[@]#*.}             #=> html.erb html.erb

# ${parameter##word}
echo ${parameter##*.}           #=> j2
echo ${array[@]##*.}            #=> erb erb

${parameter%word}、${parameter%%word}

  • parameterに対しwordで後方一致するパターンを取り除いた結果を返す。#は最短一致、##は最長一致のパターン。
  • parameterが@や*の配列変数の場合、全ての要素に対して順番に適用される。
parameter="test.sh.j2"          #=> 
array=(index.html.erb hello.html.erb)  #=> 

# ${parameter%word}
echo ${parameter%.*}            #=> test.sh
echo ${array[@]%.*}             #=> index.html hello.html

# ${parameter%%word}
echo ${parameter%%.*}           #=> test
echo ${array[@]%%.*}            #=> index hello

${parameter/pattern/string}

  • parameterのpatternの最長一致する部分をstringに置換する。
  • / で始まる場合は、patternにマッチした全てが置換される。
  • # で始まる場合は、parameterを展開した値の先頭にマッチ。
  • %で始まる場合は、parameterを展開した値の末尾にマッチ。
  • parameterが、@や*の場合は、全ての要素に適用される。
parameter="# this is a comment line."  #=> 
array=("# this is a comment line." "# this is not a comment line.")  #=> 

# ${parameter/pattern/string}
echo ${parameter/i/I}           #=> # thIs is a comment line.
echo ${parameter//i/I}          #=> # thIs Is a comment lIne.
echo ${parameter[*]//i/I}       #=> # thIs Is a comment lIne.

echo ${parameter/##/#=>}        #=> #=> this is a comment line.
echo ${parameter/#this/This}    #=> # this is a comment line.
echo ${parameter[@]/#this/This}  #=> # this is a comment line.

echo ${parameter/%./!}          #=> # this is a comment line!
echo ${parameter/%e/!}          #=> # this is a comment line.
echo ${parameter[@]/%e/!}       #=> # this is a comment line.

${parameter^pattern}、${parameter^^pattern}、${parameter,pattern}、${parameter,,pattern}

  • parameterに含まれるアルファベットの大文字小文字を変換する。
  • ^ は、patternにマッチした小文字を大文字に変換し、, は、大文字を小文字に変換する。これらは、最初にマッチした部分のみ置換する。
  • ^^ と ,, は、マッチした全ての文字を置換する。
  • parameterが、@や* の場合は、全ての要素に適用される。
parameter="hellO, WOrld"        #=> 
array=("hellO, WOrld" "hellO, WOrld2")  #=> 

# ${parameter^pattern}
echo ${parameter^l}             #=> hellO, WOrld
echo ${array[@]^l}              #=> hellO, WOrld hellO, WOrld2

# ${parameter^^pattern}
echo ${parameter^^l}            #=> heLLO, WOrLd
echo ${array[@]^^l}             #=> heLLO, WOrLd heLLO, WOrLd2

# ${parameter,pattern}
echo ${parameter,O}             #=> hellO, WOrld
echo ${array[@],,O}             #=> hello, World hello, World2

# ${parameter,,pattern}
echo ${parameter,,O}            #=> hello, World
echo ${array[@],,O}             #=> hello, World hello, World2

プロセス置換

  • >(list)は、ファイルへの出力がlistへの入力となる。
  • <(list)は、listの出力がファイルへの入力となる。

サンプル lsの結果で*.shファイルのみを出力

  1. a=
  2. while IFS= read -r line
  3. do
  4.   a="$line:$a"
  5. done < <(ls . | grep -e "\.sh$")

サンプル a.txtとb.txtをdiffの入力ファイルとして比較

  1. diff -u <(cat a.txt) <(cat b.txt)

サンプル

  1. exec 3>&1
  2. exec > >(while read line; do echo "$(date): $line";done)
  3.  
  4. echo "hello"
  5. echo "bar"
  6.  
  7. exec 1>&3 3>&-

execを使った入出力のリダイレクト

execコマンドでリダイレクトだけを指定すると、シェル自身のファイル記述子とデバイスの対応を変更することができる。

execを使った入力のリダイレクト
  1. # copy stdin to descriptor 3
  2. exec 3<&0
  3.  
  4. # redirect stdin to test.c
  5. exec < test.c
  6.  
  7. # read a line from test.c
  8. read line
  9. echo $line
  10.  
  11. # restore stdin and close descriptor 3
  12. exec 0<&3 3<&-
execを使った出力のリダイレクト
  1. # save stdout as descriptor 3
  2. exec 3>&1
  3.  
  4. exec > test.txt
  5.  
  6. echo "this message is written into the test.txt"
  7.  
  8. # restore stdout and close descriptor 3
  9. exec 1>&3 3>&-

特定の式や文の出力をまとめてリダイレクトしたい場合は、ブレースを使った複合コマンドでも処理できる。

複合コマンドの出力をファイルにリダイレクトする

  1. #!/usr/bin/env bash
  2.  
  3. # 複合コマンド
  4. {
  5.   # stdout.txtに出力
  6.   echo "this message is written into stdout.txt"
  7.   # stderr.txtに出力
  8.   echo "this message is written into stderr.txt" >&2
  9. } > stdout.txt 2> stderr.txt

参考リンク

[PR]

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2019-02-02 (土) 00:46:16 (46d)
GO TO TOP