Bash Basics | Basicsトップページ | トップページ
展開
シェルはコマンド行の処理を行う際、クォートされていない文字列をメタ文字で区切って単語に分割します。
さらに単語に分割されたコマンド行の文字列に対して、ブレース展開、チルダ展開、パラメータ展開、コマンド置換、算術式展開、プロセス置換(サポートされているシステムのみ)、単語の分割、パス名展開を行って処理すべきコマンド行の文字列を最終的に組み立てます。
予約語やメタ文字、制御演算子はシェルでは特別な意味を持ちます。
これらの文字列を単純な文字列として扱いたい場合や、パラメータ展開を抑止するためにクォートを使用します。
クォートを行う方法は以下の3通りがあります。
バックスラッシュ エスケープシーケンス | デコードされる文字 |
---|---|
\a | 警告(ベル) |
\b | バックスペース |
\e \E | 制御文字のエスケープ文字(\x1b) |
\f | フォームフィード |
\n | 改行文字 |
\r | 復帰(Carriage Return) |
\t | 水平タブ |
\v | 垂直タブ |
\\ | バックスラッシュ |
\' | シングルクォート |
\" | ダブルクォート |
\<nnn> | 8進数値が<nnn>である8ビット文字 |
\x<HH> | 16進数値が<HH>である8ビット文字 |
\u<HHHH> | 16進数値が<HHHH>であるユニコード(ISO/IEC 10646)文字 |
\U<HHHHHHHH> | 16進数値が<HHHHHHHH>であるユニコード(ISO/IEC 10646)文字 |
\c<x> | Control-xの文字 |
|
3つの方法(エスケープ文字、シングルクォート、ダブルクォート)でメタ文字をクォートしています。 |
|
ダブルクォート「"」で囲まれた文字列内の$は特別な意味を失わないため、変数PWDの値を出力することができますが、シングルクォート「'」で囲まれた文字列内では文字としての$になるため、文字列として$PWDが出力されます。 ダブルクォート「"」で囲まれた文字列内の\に続く文字が$のため、\は特別な意味を失わず、$をエスケープしています。 |
|
文字列abcdを出力したあと、改行(改行文字を出力)して、再び文字列efgを出力しています。 |
|
文字列abcdを出力したあと、復帰(カーソルを行頭に移動)して、再び文字列efを出力しています。 結果として文字列abがefで上書きされて、文字列efcdが出力されます。 |
|
文字列abcdを出力したあと、バックスペース(カーソルを1文字戻す)を出力して、再び文字列efを出力しています。 結果として文字列dが消されて、文字列abcefが出力されます。 |
|
文字列abcdを出力したあと、フォームフィード(行だけ送りカーソル位置はそのまま)して、再び文字列efgを出力してから、フォームフィードを行い、最後に文字列hijkを出力しています。 |
|
16進数で\x61、\x62の値を持つ文字a、bを出力しています。 |
|
16進数で\u3042の値を持つユニコード文字「あ」を出力しています。 |
{}で囲んで任意の文字列、文字、整数を記述することで、指定されている選択肢を列挙したり、任意の2つの文字コード間の分字を列挙したり、任意の2つの整数間の数字を列挙することができます。
ブレース展開は以下の3つの部分で構成されます。
$ echo {/usr,/usr/local}{/bin,/lib}
/usr/bin /usr/lib /usr/local/bin /usr/local/lib
$ echo 今日の{天気は{晴れ,曇り,雨},気温は{高い,低い}}
今日の天気は晴れ 今日の天気は曇り 今日の天気は雨 今日の気温は高い 今日の気温は低い
$ echo 今日の{"天気は "{晴れ,曇り,雨},"気温は "{高い,低い}}
今日の天気は 晴れ 今日の天気は 曇り 今日の天気は 雨 今日の気温は 高い 今日の気温は 低い
$ mv file.{txt,doc}
{}に囲まれた文字列が順に出力されています。$ echo {0..50}
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
$ echo {00..50}
00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
$ echo {0..050}
000 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019
020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039
040 041 042 043 044 045 046 047 048 049 050
$ echo {50..10}
50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24
23 22 21 20 19 18 17 16 15 14 13 12 11 10
$ echo {00..50..3}
00 03 06 09 12 15 18 21 24 27 30 33 36 39 42 45 48
$ echo {a..z}
a b c d e f g h i j k l m n o p q r s t u v w x y z
$ echo {a..z..2}
a c e g i k m o q s u w y
$ echo {Z..A}
Z Y X W V U T S R Q P O N M L K J I H G F E D C B A
{}に整数を指定することで連続する数字を出力することができます。$ echo {0..z}
{0..z}
$ echo {あ..お}
{あ..お}
$ echo {A..z}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z [ ] ^ _ ` a b c d e f g h i
j k l m n o p q r s t u v w x y z
$ echo {]..z}
{]..z}
$ echo { ..z}
{ ..z}
正しくない記述は指定した文字列がそのまま出力されます。(コマンドの引き数や変数の値の代入時など)シェルが扱う文字列がクォートされていないチルダ「~」で単語が始まった場合、クォートされていないスラッシュ「/」が現れるまで(スラッシュがなければ全て)の後続の文字列は「チルダプレフィックス」として解釈されます。
チルダプレフィックスは下記の評価と展開が行われます。
$ echo ~user1
/home/user1
$ echo ~
/home/user1
$ echo ~/
/home/user1/
$ pwd
/home/user1/www/images
$ echo $PWD
/home/user1/www/images
$ echo ~+
/home/user1/www/images
$ echo $OLDPWD
/home/user1
$ echo ~-
/home/user1
$ echo ~2
/home/user1/www/js
$ echo ~-1
/home/user1/www/js
文字列中に$が含まれていると、パラメータ展開、コマンド置換、算術式展開が行われます。展開されるパラメータ名、変数名やシンボルはブレース{}で囲むこともできますが、ブレース{}を省略することもできます。
ブレース{}は以下の場合に必要となります。
例 | 説明 |
---|---|
${12} | 12番目の位置パラメータを表します。 |
$12 | 1番目の位置パラメータと文字2を表します。 |
例 | 説明 |
---|---|
${fist}name | 変数firstと文字列nameを表します。 |
$firstname | 変数firstnameを表します。 |
基本的な変数 | 配列変数 | 連想配列変数 | |
---|---|---|---|
値 配列は各要素の値 |
$変数名 または ${変数名} |
${変数名[キー]} | ${変数名[キー]} |
値の長さ 配列は各要素の長さ |
${#変数名} | ${#変数名[キー]} | ${#変数名[キー]} |
配列の要素数 | ${#変数名[*]} または ${#変数名[@]} |
${#変数名[*]} または ${#変数名[@]} | |
配列の全ての要素の値 * | ${変数名[*]} または ${変数名[@]} |
${変数名[*]} または ${変数名[@]} | |
配列の全てのキー値 配列の全てのキー値 * |
${!変数名[*]} または ${!変数名[@]} |
${!変数名[*]} または ${!変数名[@]} |
${変数名[*]} | 各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
---|---|
${変数名[@]} | 各要素の値が別々の単語として展開されます。 |
${!変数名[*]} | 各キーの値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全てのキーは連結された一連の文字列となります。 |
${!変数名[@]} | 各キーの値が別々の単語として展開されます。 |
$ str1="Hello World"
$ str2="Welcome to the World"
$ var=str1
$ echo ${!var}
Hello World
$ var=str2
$ echo ${!var}
Welcome to the World
$ v=str
$ i=3
$ str3=str1
$ eval echo \${\!${v}${i}}
Hello World
参照方法 | 変数 VARの値 | |||||
---|---|---|---|---|---|---|
未定義 | 定義済み(空文字列) | 定義済み(空文字列以外) | ||||
VARへの代入 | 展開結果 返される値 | VARへの代入 | 展開結果 返される値 | VARへの代入 | 展開結果 返される値 | |
${VAR=value} | 有り | value | 無し | 空文字列 | 無し | ${VAR} |
VARが未定義の場合に限り、VARへvalueが代入され、値としてvalueを返します。 VARが空文字列を含み、既に定義されている場合、VARへの代入は行われず、VARの値を返します。 | ||||||
${VAR:=value} | 有り | value | 有り | value | 無し | ${VAR} |
VARが未定義、または空文字列の場合、VARへvalueが代入され、値としてvalueを返します。 VARが空文字列を除き、既に定義されている場合、VARへの代入は行われず、VARの値を返します。 | ||||||
${VAR-value} | 無し | value | 無し | 空文字列 | 無し | ${VAR} |
VARが未定義の場合に限り、値としてvalueを返します。 VARが空文字列を含み、既に定義されている場合、VARの値を返します。 VARへの代入は行われません。 | ||||||
${VAR:-value} | 無し | value | 無し | value | 無し | ${VAR} |
VARが未定義、または空文字列の場合、値としてvalueを返します。 VARが空文字列を除き、既に定義されている場合、VARの値を返します。 VARへの代入は行われません。 | ||||||
${VAR+value} | 無し | 空文字列 | 無し | value | 無し | value |
VARが未定義の場合、空文字列を返します。 VARが空文字列の場合を含み、既に定義されている場合、値としてvalueを返します。 VARへの代入は行われません。 | ||||||
${VAR:+value} | 無し | 空文字列 | 無し | 空文字列 | 無し | value |
VARが未定義、または空文字列の場合、値として空文字列を返します。 VARが空文字列を除き、既に定義されている場合に限って、値としてvalueを返します。 VARに値は代入は行われません。 | ||||||
${VAR?value} | エラー | 無し | 空文字列 | 無し | ${VAR} | |
VARが未定義の場合、標準エラー出力に"シェル名: VAR: value"を出力してエラーを発生させます。 VARが空文字列を含み、既に定義されている場合、値としてVARの値を返します。 VARへの代入は行われません。 | ||||||
${VAR:?value} | エラー | エラー | 無し | ${VAR} | ||
VARが未定義、または空文字列の場合、標準エラー出力に"シェル名: VAR: value"を出力してエラーを発生させます。 VARが空文字列を除き、既に定義されている場合に限って、値としてVARの値を返します。 VARへの代入は行われません。 |
参照方法 | 展開結果 | 例、備考 |
---|---|---|
${VAR:offset:length} | VARの値のoffsetの位置(先頭の文字を0とし1文字ずつ数える)の文字からlengthの長さの文字列が返されます。 offsetとlengthは算術式が記述できます。 offsetが負の値の場合、VARの値の末尾からのオフセットと見做されます。 lengthが負の値の場合、VARの値の末尾からのオフセットと見做され、長さではなく、offsetの位置の文字からlengthの位置の文字までの文字列が返されます。 |
|
${VAR:offset} | VARの値のoffsetの位置(先頭の文字を0とし1文字ずつ数える)の文字から末尾までの文字列が返されます。 offsetは算術式が記述できます。 offsetが負の値の場合、VARの値の末尾からのオフセットと見做されます。 |
|
${VAR[*]:offset:length} | VARが配列変数で、キーに*が指定された場合、がoffsetの位置からlength個の配列変数の要素が返されます。 offsetが負の値の場合、最後の要素からのオフセットと見做されます。 lengthに負の値を指定することはできません。 ダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
|
${VAR[*]:offset} | VARが配列変数で、キーに*が指定された場合、offsetの位置から最後の要素までが返されます。 offsetが負の値の場合、最後の要素からのオフセットと見做されます。 ダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 | |
${VAR[@]:offset:length} | VARが配列変数で、キーに@が指定された場合、がoffsetの位置からlength個の配列変数の要素が返されます。 offsetが負の値の場合、最後の要素からのオフセットと見做されます。 lengthに負の値を指定することはできません。 |
|
${VAR[@]:offset} | VARが配列変数で、キーに@が指定された場合、offsetの位置から最後の要素までが返されます。 offsetが負の値の場合、最後の要素からのオフセットと見做されます。 | |
${*:offset:length} | 変数ではなく、*が指定された場合、offsetの位置からlength個の位置パラメータが返されます。 offsetが負の値の場合、最後の位置パラメータからのオフセットと見做されます。 offsetが0の場合、$0を始めとする位置パラメータが対象となります。 lengthに負の値を指定することはできません。 ダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
例として下記のようなスクリプトoffset.shを作成します。
実行例:
|
${*:offset} | 変数ではなく、*が指定された場合、offsetの位置から最後までの位置パラメータが返されます。 offsetが負の値の場合、最後の位置パラメータからのオフセットと見做されます。 offsetが0の場合、$0から全ての位置パラメータが返されます。 ダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定 されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素 は連結された一連の文字列となります。 | |
${@:offset:length} | 変数ではなく、@が指定された場合、offsetの位置からlength個の位置パラメータが返されます。 offsetが負の値の場合、最後の位置パラメータからのオフセットと見做されます。 offsetが0の場合、$0を始めとする位置パラメータが対象となります。 lengthに負の値を指定することはできません。 |
例として下記のようなスクリプトoffset.shを作成します。
実行例:
|
${@:offset} | 変数ではなく、@が指定された場合、offsetの位置から最後までの位置パラメータが返されます。 offsetが負の値の場合、最後の位置パラメータからのオフセットと見做されます。 offsetが0の場合、$0から全ての位置パラメータが返されます。 |
参照方法 | 展開結果 | 例 |
---|---|---|
${VAR#pattern} および ${VAR##pattern} |
VARの値の先頭からpatternに一致する部分が削除されて返されます。 ${VAR#pattern}の場合、patternは最短一致で評価されます。 ${VAR##pattern}の場合、patternは最長一致で評価されます。 キーが*、または@の配列変数、または連想配列変数をVARとして指定した場合、配列の全ての要素に対して置換が適用されてリストとして返されます。 ただし、キーが*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 *、または@をVARとして指定した場合、位置パラメータの全ての要素に対して置換が適用されてリストとして返されます。 ただし、*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
例として以下のようなremovepattern.shを作成します。
実行例:
|
${VAR%pattern} および ${VAR%%pattern} |
VARの値の後ろからpatternに一致する部分が削除されて返されます。 ${VAR%pattern}の場合、patternは最短一致で評価されます。 ${VAR%%pattern}の場合、patternは最長一致で評価されます。 キーが*、または@の配列変数、または連想配列変数をVARとして指定した場合、配列の全ての要素に対して置換が適用されてリストとして返されます。 ただし、キーが*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 *、または@をVARとして指定した場合、位置パラメータの全ての要素に対して置換が適用されてリストとして返されます。 ただし、*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
例として以下のようなremovepattern.shを作成します。
実行例:
|
${VAR/pattern/string} および ${VAR//pattern/string} |
VARの値のpatternに最長一致する部分がstringに置換されて返されます。 ${VAR/pattern/string}の場合、最初に一致した部分だけが置換されます。 ${VAR//pattern/string}の場合、一致した全ての部分が置換されます。 patternが#で始まる場合、VARの先頭と見做されます。(正規表現の^に相当します。) patternが%で始まる場合、VARの末尾と見做されます。(つまりpatternが"%abc"の場合、VARがabcで終ると一致します。) キーが*、または@の配列変数、または連想配列変数をVARとして指定した場合、配列の全ての要素に対して置換が適用されてリストとして返されます。 ただし、キーが*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 *、または@をVARとして指定した場合、位置パラメータの全ての要素に対して置換が適用されてリストとして返されます。 ただし、*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
例として以下のようなreplace.shを作成します。
実行例:
|
${VAR/pattern/}, ${VAR/pattern} および ${VAR//pattern/}, ${VAR//pattern} |
VARの値のpatternに最長一致する部分が削除されて返されます。 ${VAR/pattern/}、または${VAR/pattern}の場合、最初に一致した部分だけが削除されます。 ${VAR//pattern/}、または${VAR//pattern}の場合、一致した全ての部分が削除されます。 patternが#で始まる場合、VARの先頭と見做されます。(正規表現の^に相当します。) patternが%で始まる場合、VARの末尾と見做されます。(つまりpatternが"%abc"の場合、VARがabcで終ると一致します。) キーが*、または@の配列変数、または連想配列変数をVARとして指定した場合、配列の全ての要素に対して削除が適用されてリストとして返されます。 ただし、キーが*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 *、または@をVARとして指定した場合、位置パラメータの全ての要素に対して削除が適用されてリストとして返されます。 ただし、*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
例として以下のようなremovepattern.shを作成します。
実行例:
|
${VAR^pattern} および ${VAR^^pattern} |
VARの値のpatternに一致する文字(文字列ではないことに注意してください)が英大文字に置換されて返されます。patternは一文字と一致するように指定する必要があります。(例えば、[a-z][a-z]は2文字となるため、文字とは一致しません。) patternを省略した場合、?を指定したものと見做され、全ての英小文字が英大文字に置換されます。 ${VAR^pattern}の場合、最初に一致した文字だけが置換されます。 ${VAR^^pattern}の場合、一致した全ての文字が英大文字に置換されます。 キーが*、または@の配列変数、または連想配列変数をVARとして指定した場合、配列の全ての要素に対して置換が適用されてリストとして返されます。 ただし、キーが*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 *、または@をVARとして指定した場合、位置パラメータの全ての要素に対して置換が適用されてリストとして返されます。 ただし、*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
|
${VAR,pattern} および ${VAR,,pattern} |
VARの値のpatternに一致する文字(文字列ではないことに注意してください)が英小文字に置換されて返されます。patternは一文字と一致するように指定する必要があります。(例えば、[a-z][a-z]は2文字となるため、文字とは一致しません。) patternを省略した場合、?を指定したものと見做され、全ての英大文字が英小文字に置換されます。 ${VAR^pattern}の場合、最初に一致した文字だけが置換されます。 ${VAR^^pattern}の場合、一致した全ての文字が英小文字に置換されます。 キーが*、または@の配列変数、または連想配列変数をVARとして指定した場合、配列の全ての要素に対して置換が適用されてリストとして返されます。 ただし、キーが*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 *、または@をVARとして指定した場合、位置パラメータの全ての要素に対して置換が適用されてリストとして返されます。 ただし、*の場合でダブルクォートでクォートされていた場合、各要素の値がIFSの最初の文字で区切られた1つの単語として展開されます。 IFSが設定されていない場合には、空白文字で区切られます。 IFSが空文字列の場合には、展開される全ての要素は連結された一連の文字列となります。 |
|
以下のいずれかの形式でコマンドを記述するとそのコマンドの実行結果の標準出力に置換されます。
これにより、コマンドの引き数に別のコマンドの標準出力を与えたり、コマンドの標準出力を変数に代入したりすることができます。
$(コマンド)
または
`コマンド`
bashはサブシェル内でコマンドを実行し、コマンドの標準出力でコマンド置換の記述部分を置き換えます。
標準出力した内容の末尾にある改行文字は削除されますが、出力された内容の途中にある改行文字は削除されません。
ただし、単語分割の際に削除されることがあります。
$(コマンド)の形式の場合、()内の全ての文字がコマンド文字列として実行されます。
`コマンド`の形式の場合、バックスラッシュ「\」が前置されていないバッククォート「`」までがコマンド文字列として実行され、コマンド文字列にバックスラッシュが含まれる場合、$、`、\の前にある場合を除いて文字としてのバックスラッシュとして扱われます。
`コマンド`の形式は古い形式で使用は推奨されていません。
コマンド置換は入れ子にすることができますが、`コマンド`の形式を使った入れ子を行う場合、内側のバッククォートをバックスラッシュでエスケープする必要があります。
実行例:
$ HTTPD_PID=$(ps --noheader -opid -C httpd); echo $HTTPD_PID
1520 1717 7309 12312 12317 21135 21143 21176 21179 21180 22699 28100
実行中のhttpdのプロセスIDを取得し変数に代入しています。$ TARGET_FILES=$(ls *.txt); echo $TARGET_FILES
1.txt 11.txt 123.txt 123a.txt a.txt b.txt c.txt
処理対象のファイルを取得し変数に代入しています。$ cmd $(date --date "-1 months" +%Y%m%d)
$ DATE=($(date))
$ for ((i=0; i<${#DATE[*]}; i++)); do echo ${DATE[$i]}; done
2022年
3月
13日
日曜日
11:44:49
JST
$ if [[ $(grep -q Error error.log)$? -eq 0 ]]; then echo OK; else echo NG; fi
OK
$ if [[ $(grep -q Error error.log) $? -eq 0 ]]; then echo OK; else echo NG; fi
bash: 条件二項演算子が予期されます
bash: `$?' 周辺に構文エラーがあります
以下の形式で算術式を記述するとその算術式の評価結果に置換されます。
これにより、コマンドの引き数に算術計算の結果を与えたり、算術計算の結果を変数に代入したりすることができます。
$((式))
式に含まれる全てのトークンに対して、パラメータ展開、コマンド置換、クォートの削除が行われます。
算術式展開は入れ子にすることができます。
算術式は算術式評価に示す規則に従って評価されます。
式が不正な場合、エラーを出力し、置換は行われません。
実行例:
$ x=1; y=3; echo $((x=y+1, y=x++*2, x*y))
40
$ x=3; y=4; echo $((x**y))
81
$ x=3; y=4; echo $(( $((x++)) * ($((y++)) +x) ))
24
$ echo "abcdefghijklmnopqrstuvwxyz" | cut -c$((26-3))-
wxyz
$ eval echo \$\'\\x`printf "%x" $((97+4))`\'
e
システムが名前付きパイプ(FIFO)または、「/dev/fd」形式のファイルディスクリプタ指定をサポートしている場合、プロセス置換が使用できます。
以下のいずれかの形式でリストを記述するとリストの標準入出力がファイルへの入出力と同等に展開されます。
>(リスト)
または
<(リスト)
プロセス置換を使用するとコマンドが入力としてファイルを想定している場合、ファイルの代わりにリストの標準出力から読み込むことができます。同様にファイルへの出力を想定している場合、リストの標準入力へ書き込むことができます。
リダイレクションとは異り、コマンドの引き数にファイルを想定している(ファイル名に相当する)部分の引き数に置換することができます。
例えば、以下のように使用することができます。
実行例:
$ diff <(date) <(sleep 1;date)
1c1
< 2022年 3月 13日 日曜日 11:43:28 JST
---
> 2022年 3月 13日 日曜日 11:43:29 JST
この例ではdiffコマンドの入力として2つの<()を使う例を示しています。$ strace -f -o >(cat >trace.log) bash
この例ではstraceの出力を単純にcatで読み込んでファイルにリダイレクションしていますが、catではなく、grepなどの加工を行うコマンドをプロセス置換で使用することによってファイルに出力したものを加工するのではなく、出力時にリアルタイムに加工しながら必要なデータのみをファイルに出力するということができます。
ダブルクォートの内側以外で文字列中に$が含まれていると、パラメータ展開、コマンド置換、算術式展開が行われた後、展開の結果に対して単語の分割が行われます。(展開が行われなければ単語の分割も行われません。)
以下の文字列は単語の分割は行われません。
$ WORD="Hello World"
STR=$WORD
#!/usr/bin/bash
for ((i=1; i<=${#}; i++))
do
eval echo '\$'$i: '$'$i
done
|
IFSが未設定であるため、$WORDがパラメータ展開された後、<空白文字><タブ文字><改行文字>を区切り文字としてHelloとWorldの2つの単語としてtest.shに引き数として渡されています。 |
|
WORDがダブルクォートでクォートされているため、WORDがパラメータ展開された後、1つの単語としてtest.shに引き数として渡されています。 |
|
WORDがダブルクォートで囲まれた文字列がさらにシングルクォートでクォートされているため、ダブルクォートは特別な意味を失い単純な文字として扱われます。 WORDがパラメータ展開された後、IFSに従って2つの単語としてtest.shに渡されています。 |
|
IFSが'/'に設定されているため、$WORD1はパラメータ展開された後、単語に区切られることなく、1つの単語としてtest.shに引き数として渡されています。 $WORD2はIFSに設定されている区切り文字'/'で区切られてHelloとWorldの2つの単語としてtest.shに引き数として渡されています。 $WORD3はIFSに設定されている区切り文字'/'が連続して現れるため、それぞれの区切り文字で区切られてHelloとWorldの2つの単語の間に空文字列が単語としてtest.shに引き数として渡されています。 |
シェルのオプションnoglobが指定されていなければ、(コマンドの引き数や変数の値の代入時など)シェルが扱う文字列の単語分割を行った後で、それぞれの単語が「*」、「?」、「[」を含んでいる場合、その単語はパターンとして解釈され、パターンマッチングの規則に従ってパターンにマッチするファイル名がアルファベット順にソートされたリストに展開されます。
パス名のマッチングではディレクトリを区切るスラッシュ文字は明示的に指定する必要があります。
パス名展開の動作に関連するシェルのオプションとシェル変数は以下の通りです。
オプション またはシェル変数 | 動作 |
---|---|
nullglobオプション | 無効: パターンにマッチするファイルが存在しない場合、指定されたパターンはそのまま文字列として残ります。 有効: パターンにマッチするファイルが存在しない場合、指定されたパターンは削除され、空文字列が展開されます。 |
failglobオプション | 有効: パターンにマッチするファイルが存在しない場合、エラーメッセージが表示されコマンドの実行は失敗します。 |
nocaseglobオプション | 有効: パターンの評価に英大文字と英小文字の区別をしません。 |
globstarオプション | 有効: パス名展開でパターンに**が指定された場合、サブディレクトリを再帰的に探索し、すべてのディレクトリ、サブディレクトリとファイルにマッチします。**/が指定された場合、サブディレクトリを再帰的に探索し、すべてのディレクトリとサブディレクトリにマッチします。 |
extglobオプション | 有効: 拡張パターンマッチング演算子が使用できます。 |
dotglobオプション | 無効: .で始まるファイルを対象から削除します。 有効: .で始まるファイルをリストに含めます。 |
GLOBIGNORE変数 | このシェル変数に指定されたパターンにマッチするファイルはリストから削除されます。 パターンの例外(マッチさせたくないもの)を指定することができます。 GLOBIGNOREに空文字列以外が指定されると、dotglobオプションも同時に有効化されるため、.で始まるファイルを除外したい場合、.*をGLOBIGNOREに含める必要があります。GLOBIGNOREをunsetするとdotglobも無効化されます。 |
パターンマッチングは条件式、コマンド履歴、パス名展開で評価されます。
条件式では文字列がパターンとマッチするかどうかを評価します。コマンド履歴ではパターンにマッチする履歴を呼び出します。パス名展開ではパターンにマッチするファイル名をアルファベット順にソートしたリストに置き換えられます。
パターンに含まれる以下の特殊パターン文字「*」、「?」、「[」と「]」を単なる文字として認識させたい場合、クォートする必要があります。
パターンがクォートされている場合、パターンに含まれる特殊パターン文字はすべて単純な文字として認識されます。
$ touch 1.txt 11.txt 123.txt 123a.txt A.TXT a.txt aa.doc b.txt c.txt
$ touch 報告書.doc お知らせ.doc
$ ls
1.txt 123.txt A.TXT aa.doc c.txt 報告書.doc
11.txt 123a.txt a.txt b.txt お知らせ.doc
ファイルをtouchで作成します。$ echo *
1.txt 11.txt 123.txt 123a.txt A.TXT a.txt aa.doc b.txt c.txt お知らせ.doc 報告書.doc
$ echo ?.txt
1.txt a.txt b.txt c.txt
もよく使う*、?をパターンとして指定した例です。$ echo [0-9][0-9].txt
11.txt
$ echo ?.txt
1.txt a.txt b.txt c.txt
$ echo [報告]*
報告書.doc
$ echo [![:digit:]]*
A.TXT a.txt aa.doc b.txt c.txt お知らせ.doc 報告書.doc
[]に文字の集合をパターンとして指定した例です。$ echo [[:digit:]].txt
1.txt
$ echo [[:alpha:]].txt
a.txt b.txt c.txt
$ echo [[:jhira:]]*
お知らせ.doc
$ echo [[:jkanji:]][[:jkanji:]][[:jkanji:]].doc
報告書.doc
[]に文字クラスをパターンとして指定した例です。$ echo [[.one.]].txt
1.txt
[]に照合シンボルをパターンとして指定した例です。$ touch '*.txt'
$ ls
*.txt 11.txt 123a.txt a.txt b.txt お知らせ.doc
1.txt 123.txt A.TXT aa.doc c.txt 報告書.doc
$ rm [[.asterisk.]].txt
$ ls
1.txt 123.txt A.TXT aa.doc c.txt 報告書.doc
11.txt 123a.txt a.txt b.txt お知らせ.doc
照合シンボルを使用する例はあまりないかも知れませんが、例えば、特殊文字を含むファイルを誤って作成してしまった場合などにも対応が可能です。$ shopt -s extglob
$ echo @([[:digit:]]|[[:alpha:]]).txt
1.txt a.txt b.txt c.txt
$ echo [[:digit:][:alpha:]].txt
1.txt a.txt b.txt c.txt
$ echo *([[:digit:]]).txt
1.txt 11.txt 123.txt
$ echo *([0-9]|[ab]).txt
1.txt 11.txt 123.txt 123a.txt a.txt b.txt
$ echo *([0-9][0-9][0-9]|[ab]).*
123.txt 123a.txt a.txt aa.doc b.txt
$ shopt -s nocaseglob
$ echo *([0-9][0-9][0-9]|[ab]).txt
123.txt 123a.txt A.TXT a.txt aa.doc b.txt
シェルのオプションによる動作の変化の例です。
先行して行われる展開が全て終わった後、クォートされていない \、'、" が展開されずに残っている(展開の結果ではない)場合、全て削除されます。
実行例:
|
クォートされていない \、'、" は削除されるため、全て出力されません。 |
|
クォートされている \、'、" は削除されないため、全て出力されます。 |
|
展開の結果出力される \、'、" は削除されないため、全て出力されます。 |