Table of Contents
シェルの復習
- シェルはLinuxでOSとユーザーの仲立ちをするユーザーインターフェース
- ユーザーが入力したコマンドを解釈&実行するインタプリタのこと
sequenceDiagram
participant A as User
participant B as bash
participant C as command<br>今回はlsコマンド
B->>A: プロンプト($)の表示
A->>B: コマンド入力<br>ls command
B->>B: コマンド解析
B->>C: プロセス生成
C->>C: プロセスが処理を実行
C->>B: プロセス終了
B->>A: 結果の出力<br>file A file B
B->>A: プロンプト($)の表示
シェル変数と環境変数
シェルが扱う変数には
- シェル変数: 設定されたシェルだけが使用する変数.子プロセスには引き継がれない,
- 環境変数: 設定されたシェルとそのシェルで起動したプログラムが使用する変数,子プロセスに引き継がれる
の2種類があり,それぞれ確認方法や定義に差異があります.
TL;DR
- シェル変数は
set
で確認できるもの - 環境変数は
export
やdeclare -x
で定義するもの,env
やprintrnv
コマンドで確認できるもの
コマンドの実行結果をシェル変数に格納する
実行結果の変数定義
コマンドの実行結果をシェル変数に代入するには以下の2通りがある:
- コマンドを
$()
で囲んで, その結果をシェル変数に代入する - コマンドをバッククォートで囲んで, その結果をシェル変数に代入する
$
1
2
3
4
5
6
7
# (1) コマンドを`$()`で囲む場合
% a=$(which bash) && echo $a
/usr/bin/bash
# (2) コマンドをバッククォートで囲む場合
% a=`which bash` && echo $a
/usr/bin/bash
よくある間違いとして, =
の前後に空白をいれるとエラーになります.
1
2
% a = $(which bash) && echo $a
a: command not found
これはシェルがa
をコマンドと認識して, =
以降を引数と解釈してしまっているからです. そのため, エラーメッセージもa: command not found
となっています.
算術演算の場合
算術演算の結果を格納する場合は
expr
を用いて上の「実行結果の変数定義」と同じ方法で代入する- 二重括弧
(( ))
を用いて, 変数に代入する$
例として,
1
2
3
4
5
6
7
8
9
10
11
12
% echo $((1+1))
2
% echo `expr 1 + 1`
2
% echo $(expr 1 + 1)
2`$`
% echo `((1+1))`
% a=`date +%H%M%S` && b=$(($a+10)) && echo $a $b
172112 172122
% a=2;b=8 && echo $((b<<a))
32
注意としては二重括弧(( ))
を用いる場合はバッククォートの参照は上手く行きません.
<<
はビットシフト演算子です. 最後の二重括弧の中の変数は$
をつけないでも計算することができます. ただし, 基本的には変数は変数とわかるように$
をつけたほうが良いと考えます.
Column: 主なシェル変数
変数名 | 説明 |
---|---|
PWD |
カレントディレクトリの絶対パス |
PATH |
コマンド検索パス |
HOME |
ユーザーのホームディレクトリ |
PS1 |
プロンプト定義 |
PS2 |
2次プロンプト定義 |
HISTFILE |
コマンド利益を格納するファイルパス |
LANG |
言語情報 |
unset
コマンド: 変数を削除する
シェル変数,環境変数問わず以下のコマンドで指定した変数を削除する(=未定義に戻す)ことができます.
1
% unset 変数名
空にするだけの場合は
1
% 変数名=
でも可能です.空にする場合と未定義に戻すことに違いは シェルスクリプトなどでよく見るset -u
で未定義の変数を参照した場合にエラーを返すか返さないかの違いとなります.
1
2
3
4
5
$ echo $a
$ set -u
$ echo $a
bash: a: unbound variable
bash | zsh |
---|---|
set -u |
unsetopt unset or set -u |
set +u |
setopt unset or set +u |
一時的に変数を作成して続けて実行するコマンドに渡す
一時的にコマンドへ変数を渡す場合
一時的に変数VAR
を作成し, 続けて実行するCOMMANDにて一時的に変数VAR
を使用する場合は
以下のようにCLIへ入力する
1
$ VAR="Kirby" COMMAND
bashシェルスクリプトファイル testshell
を以下のように独自に定義する
1
2
3
#!/bin/bash
echo $VAR
このとき, シェル変数を定義するのみだとtestshell
はシェル変数を参照することができません.
1
2
3
4
5
6
$ set | grep "^VAR"
VAR=Kirby
$ set | grep "^VAR="
VAR=Kirby
$ bash testshell
一方, 以下のように同じラインで定義 & 実行をするとシェル変数を参照してくれます.
1
2
$ VAR="Kirby" bash testshell
Kirby
最後に$ echo $VAR
を続けて実行すると,あくまで$VAR
は一時的に定義された変数なので,
次回以降のプロンプトではundefinedとして処理されます.
1
2
3
4
5
6
$ VAR="Kirby" bash testshell
Kirby
# 続けて実行すると何も出力されない
$ echo $VAR
変数の操作
変数の一部を使用する:変数展開
変数名の一部を使用したい場合は, ${変数名:開始位置:長さ}
のように指定することで
部分文字列のみを抽出することができます,
指定パターン | 挙動 |
---|---|
${変数名:開始位置:長さ} |
開始位置から指定した長さ分の文字列を切り出す |
${変数名#パターン} |
パターン部分(前方一致)を削除. # の場合は最短一致 |
${変数名##パターン} |
パターン部分(前方一致)を削除. ## の場合は最長一致 |
${変数名%文字列} |
パターン部分(後方一致)を削除.% の場合は最短一致 |
${変数名%%文字列} |
パターン部分(後方一致)を削除.%% の場合は最長一致 |
${変数名:-文字列} |
変数の内容を取得. 変数がセットされていない場合は指定した文字列を返す |
${変数名:=文字列} |
変数の内容を取得. 変数がセットされていない場合は文字列. 変数がセットされていない場合は変数に指定した文字列をセットした上で返す |
${#変数名} |
変数の文字数(配列の場合は要素数) |
1
2
3
4
5
6
7
8
9
10
11
12
13
14
% echo "$LANG"
en_US.UTF-8
% echo "${LANG:0:5}" #先頭5文字
en_US
% echo "${LANG#*U}" #前方一致削除(最短)
S.UTF-8
% echo "${LANG##*U}" #前方一致削除(最長)
TF-8
% echo "${LANG%U*}" #後方一致削除(最短)
en_US.
% echo "${LANG%%U*}" #後方一致削除(最長)
en_
% echo ${#LANG}
11
文字列変数の結合
文字列変数の結合
文字列を連結させたいときは大まかに以下2種類の方法がある:
$var_A$var_B
と続けて記述- 各変数の定義後,
var_A+=$var_B
すると,$var_A
の中身が結合した文字列になる
1
2
3
4
% a="Bob"; b="Mary"; echo $a$b
BobMary
% a="Bob"; b="Mary"; a+=$b; echo $a
BobMary
文字列変数の置換
パターン | 挙動 |
---|---|
${変数/検索文字列/置換文字列} |
最初にマッチしたもののみ文字列を置換 |
${変数//検索文字列/置換文字列} |
全ての文字列を置換 |
1
2
3
4
5
6
# 前方一致
% a="bobbobobob"; echo $a ${a/ob/ca}
bobbobobob bcabobobob
# globalで変換
% a="bobbobobob"; echo $a ${a//ob/ca}
bobbobobob bcabcacaca
(注意:GitHub Accountが必要となります)