Last Update 2022/12/09
シェル変数
bashのインスタンスを呼び出すために使用される完全なファイル名に展開
現在のbashプロセスのプロセスIDに展開
[[ 式 ]] 内の=~演算子のマッチング結果が割り当てられる配列変数
サブシェルまたはサブシェル環境の作成に伴い1つずつ増加
現在実行中のbashのバージョン情報を格納する読み取り専用の配列変数
現在実行中のbashのバージョン情報を表す文字列に展開
Unix Epoch (UTCでの1970年1月1日午前0時0分0秒) からの秒数をマイクロ秒単位の浮動小数点数として展開
Unix Epoch (UTCでの1970年1月1日午前0時0分0秒) からの秒数として展開
(09) 欠番
現在コールスタックにある全シェル関数の名前が入った配列変数
現在のユーザーがメンバーであるグループのリストを含む配列変数
現在のコマンドのヒストリーリスト内のインデックス
現在のホスト名
bashが実行されているマシンの種類を一意に表す文字列を自動的に設定
この変数が参照される度に、スクリプトまたは関数内の現在の行番号(1〜)を表す10進数に置換
GNU標準の cpu-company-system 形式で、bashが実行されているシステムタイプを完全に説明する文字列を自動的に設定
組み込みコマンドmapfileが、変数名が与えられていない時に、読み込むテキストを保持するために作成される配列変数
cdコマンドでセットされた1つ前の作業ディレクトリ
組み込みコマンドgetoptsで処理される最後(現在処理中)のオプション引数の値
組み込みコマンドgetoptsで処理される次の引数のインデックス
bashが実行されているオペレーティングシステムを表す文字列が自動的に設定される
最も最近実行されたフォアグラウンドパイプラインの終了ステータス値のリストを含む配列変数
シェルの親プロセスのプロセスID
cdコマンドで設定された現在の作業ディレクトリ
参照されるたびに、0から32767までのランダムな整数に展開
値の設定で乱数のシーケンスが初期化
値の設定で乱数のシーケンスが初期化
シェル起動からの秒数
有効になっているシェルオプションをコロンで区切ったリスト
bashのインスタンスが開始される毎に1ずつ増加
参照されるたびに、32ビットの疑似乱数に展開
現在のユーザーのユーザーIDに展開
以下、シェルによって使用される変数の主なもの
現在のユーザーのホームディレクトリ
コマンドの検索パス
シェルへのフルパス名に展開
「time」の接頭辞が付いたパイプラインの情報表示方法を指定するフォーマット文字列
実行結果
$ echo $BASH
/bin/bash <--- このbashのインスタンスを呼び出すために使用される完全なファイル名
実行結果
$ echo $BASHPID
262
$ ps
PID TTY TIME CMD
262 pts/0 00:00:00 bash <--- 現在のbashプロセスのプロセスID
308 pts/0 00:00:00 ps
$ ( echo $BASHPID ; ps ) <--- サブシェル内でBASHPIDを出力
309
PID TTY TIME CMD
262 pts/0 00:00:00 bash
309 pts/0 00:00:00 bash <--- サブシェルのプロセスID
310 pts/0 00:00:00 ps
sample3.sh
#!/bin/bash
echo "例(1) [[ \$0 =~ .+\. ]]"
if [[ $0 =~ .+\. ]]; then
for (( i=0 ; i < ${#BASH_REMATCH[@]} ; ++i ))
do
echo "BASH_REMATCH[$(( i ))] = ${BASH_REMATCH[i]}"
done
fi
echo
echo "例(2) [[ \$0 =~ [a-z]+ ]]"
if [[ $0 =~ [a-z]+ ]]; then
for (( i=0 ; i < ${#BASH_REMATCH[@]} ; ++i ))
do
echo "BASH_REMATCH[$(( i ))] = ${BASH_REMATCH[i]}"
done
fi
echo
s="abc123def"
echo "例(3) [[ \$s =~ ([a-z]+)[[:digit:]]+([a-z]+) ]]"
if [[ $s =~ ([a-z]+)[[:digit:]]+([a-z]+) ]]; then
for (( i=0 ; i < ${#BASH_REMATCH[@]} ; ++i ))
do
echo "BASH_REMATCH[$(( i ))] = ${BASH_REMATCH[i]}"
done
fi
実行結果
$ ./sample3.sh
例(1) [[ $0 =~ .+\. ]]
BASH_REMATCH[0] = ./sample3. <--- インデックス0には正規表現全体にマッチした部分文字列を格納
例(2) [[ $0 =~ [a-z]+ ]]
BASH_REMATCH[0] = sample
例(3) [[ $s =~ ([a-z]+)[[:digit:]]+([a-z]+) ]]
BASH_REMATCH[0] = abc123def
BASH_REMATCH[1] = abc <--- インデックス1には最初の( )内にマッチした部分文字列を格納
BASH_REMATCH[2] = def <--- インデックス2には2番目の( )内にマッチした部分文字列を格納
sample4.sh
#!/bin/bash
subshell()
( <--- 関数内は新規サブシェルで実行
echo "BASH_SUBSHELL = $BASH_SUBSHELL"
)
echo "BASH_SUBSHELL = $BASH_SUBSHELL"
echo
subshell ; echo
( subshell ) ; echo <--- 以降、( )で新規サブシェルを生成
( ( subshell ) ) ; echo
( ( subshell ) ; ( subshell ) ; subshell ) ; echo
echo "BASH_SUBSHELL = $BASH_SUBSHELL"
実行結果
$ ./sample4.sh
BASH_SUBSHELL = 0
BASH_SUBSHELL = 1 <--- subshell
BASH_SUBSHELL = 2 <--- ( subshell )
BASH_SUBSHELL = 3 <--- ( ( subshell ) )
BASH_SUBSHELL = 3 <--- ( ( subshell ) ; ( subshell ) ; subshell )
BASH_SUBSHELL = 3
BASH_SUBSHELL = 2
BASH_SUBSHELL = 0
sample5.sh
#!/bin/bash
echo "配列要素数 : ${#BASH_VERSINFO[@]}"
echo
echo "BASH_VERSINFO[0] : メジャーバージョン番号"
echo "---> ${BASH_VERSINFO[0]}"
echo
echo "BASH_VERSINFO[1] : マイナーバージョン番号"
echo "---> ${BASH_VERSINFO[1]}"
echo
echo "BASH_VERSINFO[2] : パッチレベル"
echo "---> ${BASH_VERSINFO[2]}"
echo
echo "BASH_VERSINFO[3] : ビルドバージョン"
echo "---> ${BASH_VERSINFO[3]}"
echo
echo "BASH_VERSINFO[4] : リリースステータス"
echo "---> ${BASH_VERSINFO[4]}"
echo
echo "BASH_VERSINFO[5] : MACHTYPEの値"
echo "---> ${BASH_VERSINFO[5]}"
echo
実行結果
$ ./sample5.sh
配列要素数 : 6
BASH_VERSINFO[0] : メジャーバージョン番号
---> 5
BASH_VERSINFO[1] : マイナーバージョン番号
---> 1
BASH_VERSINFO[2] : パッチレベル
---> 16
BASH_VERSINFO[3] : ビルドバージョン
---> 1
BASH_VERSINFO[4] : リリースステータス
---> release
BASH_VERSINFO[5] : MACHTYPEの値
---> x86_64-pc-linux-gnu
実行結果
$ echo ${BASH_VERSINFO[@]}
5 1 16 1 release x86_64-pc-linux-gnu <--- BASH_VERSINFOに格納されている情報
$ echo $BASH_VERSION
5.1.16(1)-release <--- BASH_VERSINFOのMACHTYPEの値を除く情報を出力
実行結果
$ echo $EPOCHREALTIME
1656851905.911670 <--- Unix Epoch (UTCでの1970年1月1日午前0時0分0秒) からの秒数(マイクロ秒単位)
$ date -u -d '@1656851905.911670' "+%F %T.%6N"
2022-07-03 12:38:25.911670 <--- EPOCHREALTIMEの値をdateコマンドでUTCにて出力
$ date -d '@1656851905.911670' "+%F %T.%6N"
2022-07-03 21:38:25.911670 <--- EPOCHREALTIMEの値をdateコマンドでローカル時刻にて出力
実行結果
$ echo $EPOCHSECONDS
1656852716 <--- Unix Epoch (UTCでの1970年1月1日午前0時0分0秒) からの秒数
$ date -u -d '@1656852716'
Sun 3 Jul 12:51:56 UTC 2022 <--- EPOCHSECONDSの値をdateコマンドでUTCにて出力
$ date -d '@1656852716'
Sun 3 Jul 21:51:56 JST 2022 <--- EPOCHSECONDSの値をdateコマンドでローカル時刻にて出力
sample10.sh
#!/bin/bash
func1()
{
echo "func1()内"
echo "FUNCNAME要素数 : ${#FUNCNAME[@]}"
echo "FUNCNAME要素 : ${FUNCNAME[@]}"
echo
echo "func1からfunc2を呼び出す"
func2
}
func2()
{
echo "func2()内"
echo "FUNCNAME要素数 : ${#FUNCNAME[@]}"
echo "FUNCNAME要素 : ${FUNCNAME[@]}"
echo
}
echo "関数外"
echo "FUNCNAME要素数 : ${#FUNCNAME[@]}"
echo "FUNCNAME要素 : ${FUNCNAME[@]}"
echo
func1
func2
echo "関数外"
echo "FUNCNAME要素数 : ${#FUNCNAME[@]}"
echo "FUNCNAME要素 : ${FUNCNAME[@]}"
echo
実行結果
$ ./sample10.sh
関数外
FUNCNAME要素数 : 0 <--- 関数未実行の場合は存在しない
FUNCNAME要素 :
func1()内
FUNCNAME要素数 : 2
FUNCNAME要素 : func1 main <--- インデックス0は実行中の関数。最後の要素はmain
func1からfunc2を呼び出す
func2()内
FUNCNAME要素数 : 3
FUNCNAME要素 : func2 func1 main
func2()内
FUNCNAME要素数 : 2
FUNCNAME要素 : func2 main
関数外
FUNCNAME要素数 : 0
FUNCNAME要素 :
実行結果
$ echo ${#GROUPS[@]}
2 <--- 配列要素数
$ echo ${GROUPS[@]}
1001 1002 <--- 配列要素リスト
$ id
uid=1001(testusr) gid=1001(testusr) groups=1001(testusr),1002(testgroup) <--- groupsと一致
実行結果
$ history -c <--- ヒストリーリストをクリア
$ echo "1"
1
$ echo "2"
2
$ echo "3"
3
$ echo $HISTCMD
4 <--- この時点のインデックスは4
$ history
1 echo "1"
2 echo "2"
3 echo "3"
4 echo $HISTCMD <--- ヒストリーリストのインデックス4
5 history
$ !4 <--- 4番目のコマンドラインを参照
echo $HISTCMD <--- ヒストリーリストのインデックス4のコマンドラインが実行される
6 <--- この時点のインデックスは6
$ history
1 echo "1"
2 echo "2"
3 echo "3"
4 echo $HISTCMD
5 history
6 echo $HISTCMD
7 history
実行結果
$ echo $HOSTNAME
test001
$ cat /etc/hostname
test001 <--- 設定されるホスト名と一致
実行結果
$ echo $HOSTTYPE
x86_64 <--- bashが実行されているマシンの種類を一意に表す文字列
sample15.sh
(行番号付き出力)
1 #!/bin/bash
2
3 func1()
4 {
5 echo "func1() 1行目"
6 echo "func1() 2行目"
7 echo "$LINENO"
8 echo "func1() 4行目"
9 echo
10 }
11
12 func2()
13 {
14 echo "$LINENO"
15 echo "func2() 2行目"
16 echo
17 }
18
19 func1
20 echo "$LINENO"
21 func2
22 echo "$LINENO"
実行結果
$ ./sample15.sh
func1() 1行目
func1() 2行目
7 <--- スクリプト先頭行からの行数
func1() 4行目
20 <---
14 <---
func2() 2行目
22 <---
実行結果
$ echo $MACHTYPE
x86_64-pc-linux-gnu <--- GNU標準の cpu-company-system 形式で、bashが実行されているシステムタイプを完全に説明する文字列
sample16.txt
abc
def
ghi
jkl
mno
実行結果
$ mapfile < sample16.txt <--- mapfileコマンドで標準入力からテキストの読み込み
$ echo ${#MAPFILE[@]} <--- 変数名指定が無いため配列変数MAPFILEに読み込まれる
5 <--- 読み込まれた要素数
$ echo ${MAPFILE[@]}
abc def ghi jkl mno <--- 配列変数MAPFILEの要素
実行結果
$ pwd
/home/testusr <--- 現在の作業ディレクトリ
$ cd .. <--- cdコマンドで一つ上のディレクトリに移動
$ echo $OLDPWD
/home/testusr <--- 一つ前の作業ディレクトリ
$ cd testusr/
$ echo $OLDPWD
/home
$ cd /usr/
$ echo $OLDPWD
/home/testusr
$ cd /home/testusr/
$ echo $OLDPWD
/usr
$ cd /home/testusr/ <--- cdコマンドで現在の作業ディレクトリを指定
$ echo $OLDPWD
/home/testusr <--- cdコマンドの指定が有効となりOLDPWDの値も現在の作業ディレクトリとなる
$ pwd
/home/testusr
sample19.sh
#!/bin/bash
while getopts "a:b:" c
do
case "$c" in
a)
echo "オプション -a"
echo "オプション引数 : $OPTARG" ;;
b)
echo "オプション -b"
echo "オプション引数 : $OPTARG" ;;
esac
done
実行結果
$ ./sample19.sh -a test1 -b test2 <--- サンプルスクリプトにオプションとオプション引数を付けて実行
オプション a
オプション引数 : test1 <--- オプション a の引数
オプション b
オプション引数 : test2 <--- オプション b の引数
sample20.sh
#!/bin/bash
echo "最初に処理する引数インデックス : $OPTIND"
while getopts "abc" c
do
case "$c" in
a)
echo "オプション -a"
echo "次に処理するインデックス : $OPTIND" ;;
b)
echo "オプション -b"
echo "次に処理するインデックス : $OPTIND" ;;
c)
echo "オプション -c"
echo "次に処理するインデックス : $OPTIND" ;;
esac
done
実行結果
$ ./sample20.sh -a -b -c <--- サンプルスクリプトにオプションを付けて実行
最初に処理する引数インデックス : 1
オプション -a
次に処理するインデックス : 2
オプション -b
次に処理するインデックス : 3
オプション -c
次に処理するインデックス : 4
実行結果
$ echo $OSTYPE
linux-gnu <--- bashが実行されているオペレーティングシステムを表す文字列
sample22_1.c(実行ファイル sample22_1)
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
if (argc > 1)
{
/* 引数有りの場合は、引数の値を標準出力へ */
printf("%d", atoi(argv[1]));
}
else
{
/* 引数有りの場合は、「1」を標準出力へ */
printf("1");
}
/* 終了ステータスとして0を返す */
return 0;
}
sample22_2.c(実行ファイル sample22_2)
#include <stdio.h>
int main(void)
{
int n;
/* 標準入力から整数値を取得 */
scanf("%d", &n);
/* 取得内容を終了ステータスとして返す */
return n;
}
実行結果
$ ./sample22_1 | ./sample22_2 | ./sample22_1 2 | ./sample22_2
$ echo ${PIPESTATUS[@]}
0 1 0 2 <--- PIPESTATUS配列変数内に直前に実行されたパイプラインの各プロセスの終了ステータスを格納
実行結果
$ ps
PID TTY TIME CMD
301 pts/0 00:00:00 bash
323 pts/0 00:00:00 ps
$ bash <--- 現在実行中のシェル「301」からシェルを起動
$ ps
PID TTY TIME CMD
301 pts/0 00:00:00 bash
324 pts/0 00:00:00 bash <--- 追加となったプロセス(bash)
325 pts/0 00:00:00 ps
$ echo $PPID
301 <--- 親プロセスのプロセスID(bash)
$ bash <--- さらに現在実行中のシェル「324」からシェルを起動
$ ps
PID TTY TIME CMD
301 pts/0 00:00:00 bash
324 pts/0 00:00:00 bash
326 pts/0 00:00:00 bash <--- 追加となったプロセス(bash)
327 pts/0 00:00:00 ps
$ echo $PPID
324 <--- 親プロセスのプロセスID(bash)
実行結果
$ echo $PWD
/home/testusr <--- cdコマンドで設定された現在の作業ディレクトリ
$ cd ..
$ echo $PWD
/home <--- 〃
$ cd /usr/local/
$ echo $PWD
/usr/local <--- 〃
$ cd
$ echo $PWD
/home/testusr <--- 〃
実行結果
$ echo $RANDOM
12449 <--- 参照する毎にランダムな整数に展開
$ echo $RANDOM
25972 <--- 〃
$ echo $RANDOM
1317 <--- 〃
$ echo $RANDOM
14819 <--- 〃
$ echo $RANDOM
1173 <--- 〃
$ RANDOM=1 <--- RANDOMを1に設定
$ echo $RANDOM
16807
$ echo $RANDOM
10791
$ echo $RANDOM
19566
$ RANDOM=1 <--- RANDOMを再度1に設定
$ echo $RANDOM
16807 <--- シード値が同じであれば以降の生成される乱数も同じ値となる
$ echo $RANDOM
10791
$ echo $RANDOM
19566
実行結果
$ date ; echo $SECONDS
Tue 12 Jul 16:52:34 JST 2022 <--- 現在時刻
25 <--- シェル起動からの秒数
$ date ; echo $SECONDS
Tue 12 Jul 16:52:39 JST 2022
30
$ date ; echo $SECONDS
Tue 12 Jul 16:52:49 JST 2022
40
$ SECONDS=0 ; date <--- SECONDSを0に設定
Tue 12 Jul 16:53:21 JST 2022 <--- 0に設定した時刻
$ date ; echo $SECONDS
Tue 12 Jul 16:53:29 JST 2022 <--- 0に設定後8秒経過
8 <--- SECONDSの値も8秒
$ date ; echo $SECONDS
Tue 12 Jul 16:53:34 JST 2022
13
$ SECONDS=1000 ; date <--- SECONDSを1000に設定
Tue 12 Jul 17:00:44 JST 2022 <--- 1000に設定した時刻
$ date ; echo $SECONDS
Tue 12 Jul 17:00:50 JST 2022 <--- 1000に設定後6秒経過
1006 <--- SECONDSの値は1000+6秒
$ date ; echo $SECONDS
Tue 12 Jul 17:00:55 JST 2022
1011
実行結果
$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor <--- 現在のシェルオプションリスト
$ echo {肉,魚}{が,も}食べたい
肉が食べたい 肉も食べたい 魚が食べたい 魚も食べたい <--- ブレース展開が有効
$ set +o braceexpand <--- braceexpandオプションを無効化
$ echo $SHELLOPTS
emacs:hashall:histexpand:history:interactive-comments:monitor <--- リストからbraceexpandが外れる
$ echo {肉,魚}{が,も}食べたい
{肉,魚}{が,も}食べたい <--- ブレース展開は無効
$ set -o braceexpand <--- braceexpandオプションを有効化
$ echo $SHELLOPTS
braceexpand:emacs:hashall:histexpand:history:interactive-comments:monitor <--- リストにbraceexpandが戻る
$ echo {肉,魚}{が,も}食べたい
肉が食べたい 肉も食べたい 魚が食べたい 魚も食べたい
実行結果
$ echo $SHLVL
1
$ bash <--- bashインスタンスを開始
$ echo $SHLVL
2 <--- SHLVLが1増加
$ bash
$ echo $SHLVL
3
$ exit
exit <--- bashインスタンスを終了
$ echo $SHLVL
2 <--- SHLVLが1減少
$ exit
exit
$ echo $SHLVL
1
実行結果
$ echo $SRANDOM <--- SRANDOMを参照
1941324080 <--- 32ビット疑似乱数
$ echo $SRANDOM
701470467
$ echo $SRANDOM
4246103850
$ SRANDOM=1 <--- SRANDOMに1を設定
$ echo $SRANDOM
3127740232
$ echo $SRANDOM
2730929198
$ SRANDOM=1 <--- 再度SRANDOMに1を設定
$ echo $SRANDOM
2985074723 <--- SRANDOMへの値の設定の効果は見られない
$ echo $SRANDOM
1001031370
実行結果
$ echo $UID
1001
$ id
uid=1001(testusr) gid=1001(testusr) groups=1001(testusr),1002(testgroup) <--- uidと一致
実行結果
$ echo $HOME
/home/testusr <--- 現在のユーザーのホームディレクトリ
実行結果
$ echo $PATH
/bin:/usr/bin <--- コマンドの検索パス
実行結果
$ echo $SHELL
/bin/bash <--- シェルへのフルパス名
実行結果(1)
$ unset TIMEFORMAT <--- TIMEFORMATが未設定の場合
$ time sleep 3 | echo $TIMEFORMAT
<--- 未設定のため出力なし
real 0m3.002s <--- 「\nreal\t%3lR\nuser\t%3lU\nsys\t%3lS」が設定された場合と同じように表示
user 0m0.001s
sys 0m0.000s
実行結果(2)
$ TIMEFORMAT=$'\n%R\n%U\n%S'
$ time sleep 3 | echo $TIMEFORMAT
%R %U %S
3.003
0.000
0.002
%R : 経過時間(秒)
%U : ユーザーモードで使用されたCPU秒数
%S : システムモードで使用されたCPU秒数
実行結果(3)
$ TIMEFORMAT=$'\n%lR\n%lU\n%lS'
$ time sleep 3 | echo $TIMEFORMAT
%lR %lU %lS
0m3.002s <--- 「l」オプションにより長い形式で出力
0m0.001s
0m0.000s
実行結果(4)
$ TIMEFORMAT=$'\n%2R\n%2U\n%2S'
$ time sleep 3 | echo $TIMEFORMAT
%2R %2U %2S
3.00 <--- 小数点以下2桁
0.00
0.00
実行結果(5)
$ TIMEFORMAT=$'\n(%U + %S) / %R --- %P(%%)'
$ time sleep 3 | echo $TIMEFORMAT
(%U + %S) / %R --- %P(%%)
(0.001 + 0.000) / 3.002 --- 0.04(%)
%P : (%U + %S) / %R (%)
%% : 「%」のリテラル
実行環境
GNU bash, version 5.1.16
GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1
GCC-8.2.0
GNU C Library 2.28
GNU Binutils 2.31.1
コード例・出力内容中の表記
・実行例中の太字表記部分は、コマンドなどの入力された文字列を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。
・「︙」や「...」の着色省略表記は、 実際のソースコードや出力内容などを省略加工した部分を示します。