「シェルスクリプトの基礎 - 変数」の版間の差分

提供:MochiuWiki - SUSE, Electronic Circuit, PCB
ナビゲーションに移動 検索に移動
(文字列「__FORCETOC__」を「{{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This pag…)
 
(同じ利用者による、間の20版が非表示)
5行目: 5行目:
== 変数の定義と参照 ==
== 変数の定義と参照 ==
変数へ値を代入する時は$を付けず、変数を参照するときは$を付ける。<br>
変数へ値を代入する時は$を付けず、変数を参照するときは$を付ける。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/sh
  #!/bin/sh
   
   
12行目: 12行目:
  echo "Hello $name"  # ダブルクォーテーションは変数を展開する
  echo "Hello $name"  # ダブルクォーテーションは変数を展開する
  echo 'Hello $name'  # シングルクォーテーションは変数を展開しない
  echo 'Hello $name'  # シングルクォーテーションは変数を展開しない
  </source>
  </syntaxhighlight>
<br>
<br>
  # 出力
  # 出力
20行目: 20行目:
<br>
<br>
未定義の変数を参照すると、空文字列と同様に扱われる。(エラーにはならない)<br>
未定義の変数を参照すると、空文字列と同様に扱われる。(エラーにはならない)<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/sh
  #!/bin/sh
   
   
  echo "Hello $name !"
  echo "Hello $name !"
  </source>
  </syntaxhighlight>
<br>
<br>
  # 出力
  # 出力
  Hello  !
  Hello  !
<br>
変数の内容の一部を取得する場合は、<code>${変数名:開始位置:長さ}</code>と指定する。<br>
なお、先頭の開始位置は0である。<br>
<br>
指定した文字列までを削除する場合、<code>${変数名#文字列}</code>と指定する。<br>
文字列を後ろから削除する場合、<code>${変数名%文字列}</code>と指定する。<br>
また、文字列の指定には、ワイルドカード*が使用できる。<br>
<br>
以下の例では、(1)環境変数LANGの0文字目から5文字分のみ取得、(2).(ドット)文字までを削除、(3).(ドット)文字以降を削除を行っている。<br>
なお、操作を指定せず${変数名}とする場合、$変数名と同義になる。<br>
<syntaxhighlight lang="sh">
#! /bin/bash
echo "$LANG" # 環境変数LANGの内容を表示
echo "${LANG:0:5}" # (1) LANGの0文字目から5文字分のみ表示
echo "${LANG#*.}" # (2) .文字までを削除
echo "${LANG%.*}" # (3) .文字以降を削除
</syntaxhighlight>
<br>
# 出力
ja_JP.utf8    # 環境変数LANGの内容
ja_JP          # ${LANG:0:5}の結果
utf8          # ${LANG#*.}の結果
ja_JP          # ${LANG%.*}の結果
<br>
下表に、主な変数の操作を示す。<br>
<center>
{| class="wikitable" | style="background-color:#fefefe;"
|-
! style="background-color:#66CCFF;" | 指定方法
! style="background-color:#66CCFF;" | 操作内容
|-
| ${変数名:開始位置:長さ} || 開始位置から指定した長さ分の文字列を切り出す
|-
| ${変数名#パターン}<br>${変数名##パターン} || パターン部分(前方一致)を削除する。<br>#の場合は最短一致、##の場合は最長一致となる。
|-
| ${変数名%文字列}<br>${変数名%%文字列} || パターン部分(後方一致)を削除する。<br>%の場合は最短一致、%%の場合は最長一致となる。
|-
| ${変数名:-文字列} || 変数の内容を取得する。<br>変数がセットされていない場合、指定した文字列を返す。
|-
| ${変数名:=文字列} || 変数の内容を取得する。<br>変数がセットされていない場合、指定した文字列を変数に代入して返す。
|-
| ${#変数名} || 変数の文字数を取得する。(配列の場合は要素数)
|}
</center>
<br>
下表に、その他の文字列の操作を示す。<br>
<center>
{| class="wikitable" | style="background-color:#fefefe;"
|-
! style="background-color:#66CCFF;" | 指定方法
! style="background-color:#66CCFF;" | 操作内容
|-
| ${@:2} || 2つ目以降の引数を取得する。
|-
| ${変数名:-文字列} || "変数名"が未定義またはNULLの場合、"文字列"が代入される。
|-
| ${変数名:=文字列} || "変数名"が未定義またはNULLの場合、"文字列"が代入される。
|-
| ${変数名:?文字列} || "変数名"が未定義またはNULLの場合、"文字列"とエラーを出力して終了する。
|-
| ${変数名:+文字列} || "変数名"が未定義またはNULLの場合はNULLを代入して、それ以外の場合は"文字列"を代入する。
|-
| ${変数名%文字列} || 最短の接尾語を取り除く。<br>例えば、拡張子名を削除する時に使用する。
|-
| ${変数名%%文字列} || 最長の接尾語を取り除く。
|-
| ${変数名#文字列} || 最短の接頭語を取り除く。<br>例えば、ディレクトリのパス名から文字列$HOMEを削除する時に使用する。
|-
| ${変数名##文字列} || 最長の接頭語を取り除く。<br>例えば、ディレクトリのパス名から任意の文字列を削除する時に使用する。
|-
| $'文字列' || Bashのみ使用可能。<br>例えば、<code>echo 'a\te';</code>と記述する場合は<code>a\te</code>と出力されるが、<br><code>echo $'a\te'</code>と記述する場合は<code>a e</code>と出力される。<br>\UhhhhhhhhとUnicode(ISO/IEC 10646 )がある。
|}
</center>
<br>
Shell Parameter Expansion(:)の有無により、変数が定義されているかどうか、および、値がNULLかどうかで動作が変わる。<br>
<center>
{| class="wikitable" | style="background-color:#fefefe;"
|-
! style="background-color:#66CCFF;" | 指定方法
! style="background-color:#66CCFF;" | 変数が定義されており値がNULLではない場合
! style="background-color:#66CCFF;" | 変数が定義されており値がNULLの場合
! style="background-color:#66CCFF;" | 変数が未定義の場合
|-
| ${変数名:-文字列} || 既存の値を返す。 || "文字列"を返す。 || "文字列"を返す。
|-
| ${変数名-文字列} || 既存の値を返す。 || NULLを返す。 || "文字列"を返す。
|-
| ${変数名:=文字列} || 既存の値を返す。 || "文字列"を代入する。 || "文字列"を代入する。
|-
| ${変数名=文字列} || 既存の値を返す。 || NULLを返す。 || "文字列"を代入する。
|-
| ${変数名:?文字列} || 既存の値を返す。 || エラーを出力して終了する。 || エラーを出力して終了する。
|-
| ${変数名?文字列} || 既存の値を返す。 || NULLを返す。 || エラーを出力して終了する。
|-
| ${変数名:+文字列} || "文字列"を返す。 || NULLを返す。 || NULLを返す。
|-
| ${変数名+文字列} || "文字列"を返す。 || "文字列"を返す。 || NULLを返す。
|}
</center>
<br>
以下に、接尾語および接頭語を示す。<br>
<syntaxhighlight lang="sh">
#!/usr/bin/env bash
hoge="${HOME}/hoge/bake/file.c"
echo 'original'
echo $hoge
echo ''
echo '${parameter%word}'
echo ${hoge%.c}.o
echo ''
echo '${parameter%%word}'
echo ${hoge%%file.c}new_file.o
echo ''
echo '${parameter#word}'
echo ${hoge#$HOME}
echo ''
echo '${parameter##word}'
echo ${hoge##*/}
</syntaxhighlight>
<br>
# 出力
original
/Users/yasui/hoge/bake/file.c
${parameter%word}
/Users/yasui/hoge/bake/file.o
${parameter%%word}
/Users/yasui/hoge/bake/new_file.o
${parameter#word}
/hoge/bake/file.c
${parameter##word}
file.c
<br><br>
<br><br>


== 定数 ==
== 定数 ==
以下のように実行すると、指定した変数や関数に対する代入、<code>unset</code>ができなくなる。<br>
以下のように実行すると、指定した変数や関数に対する代入、<code>unset</code>ができなくなる。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  readonly var      # 変数varをreadonlyにする
  readonly var      # 変数varをreadonlyにする
  readonly -a arr  # 配列arrをreadonlyにする
  readonly -a arr  # 配列arrをreadonlyにする
  readonly -f func  # 関数funcをreadonlyにする
  readonly -f func  # 関数funcをreadonlyにする
  </source>
  </syntaxhighlight>
<br>
<br>
以下のように、変数の定義と同時にreadonlyを指定することも可能である。<br>
以下のように、変数の定義と同時にreadonlyを指定することも可能である。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  readonly USERNAME="Mike"
  readonly USERNAME="Mike"
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例では、変数MAX_SIZEを100で初期化した後、200という値を代入しようとしている。<br>
以下の例では、変数MAX_SIZEを100で初期化した後、200という値を代入しようとしている。<br>
変数MAX_SIZEは定数化されているので、代入しようとした場合はエラーになる。<br>
変数MAX_SIZEは定数化されているので、代入しようとした場合はエラーになる。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/bash
   
   
  readonly MAX_SIZE=100
  readonly MAX_SIZE=100
  MAX_SIZE=200
  MAX_SIZE=200
  </source>
  </syntaxhighlight>
<br>
<br>
  # 出力
  # 出力
68行目: 211行目:
==== 変数に値が代入されていることを確認する ====
==== 変数に値が代入されていることを確認する ====
以下の例では、変数NAMEの値がセットされているか調べている。<br>
以下の例では、変数NAMEの値がセットされているか調べている。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/bash
   
   
74行目: 217行目:
     echo $NAME
     echo $NAME
  fi
  fi
  </source>
  </syntaxhighlight>
<br>
<br>
==== 変数に値が代入されていないことを確認する ====
==== 変数に値が代入されていないことを確認する ====
以下の例では、変数NAMEの値がセットされていないか調べている。<br>
以下の例では、変数NAMEの値がセットされていないか調べている。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/bash
   
   
84行目: 227行目:
     echo 'NAME is not set'
     echo 'NAME is not set'
  fi
  fi
  </source>
  </syntaxhighlight>
<br>
<br>
  # 出力
  # 出力
93行目: 236行目:
==== 加算 / 減算 ====
==== 加算 / 減算 ====
変数の値に対して、加算および減算を行うには以下のように記述する。<br>
変数の値に対して、加算および減算を行うには以下のように記述する。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/bash
   
   
99行目: 242行目:
  let val=$val+200
  let val=$val+200
  echo $val
  echo $val
  </source>
  </syntaxhighlight>
または
または
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/bash
   
   
107行目: 250行目:
  val=$(($val+200))
  val=$(($val+200))
  echo $val
  echo $val
  </source>
  </syntaxhighlight>
<br>
# 出力
300
<br>
<syntaxhighlight lang="sh">
#! /bin/bash
VALUE1="100"
VALUE2="200"
expr "$VALE1" "+" "$VALUE2"
# または
expr $VALUE1 + $VALUE2
# または
VALUE3=`expr "$str1" "+" "$str2"`
echo "$VALUE3"
</syntaxhighlight>
<br>
<br>
  # 出力
  # 出力
300
300
  300
  300
<br>
整数の演算では、<code>expr</code>コマンドまたは<code>let</code>コマンドを使用するが、<br>
実数を演算では、bcコマンドを使用する。<br>
また、bcコマンドも制御構文を使用したスクリプト処理が可能である。<br>
<syntaxhighlight lang="sh">
#! /bin/bash
VALUE1=10.5
VALUE2=3.2
echo $VALUE1 + $VALUE2 | bc
ANS=`echo $VALUE1*$VALUE2 | bc`
echo $ANS
</syntaxhighlight>
<br>
下表に、<code>let</code>コマンドで使用できる演算子を示す。(四則演算は省略)<br>
<center>
{| class="wikitable"
|-
! 演算子 !! 説明
|-
| <変数名>++<br><変数名>-- || 変数を評価した後でインクリメントまたはデクリメントする。
|-
| ++<変数名><br>--<変数名> || 変数をインクリメントしてから評価する、変数をデクリメントしてから評価する
|-
| ** || 累乗
|-
| % || 剰余
|-
| ~ || ビット単位の否定
|-
| << || 左ビットシフト
|-
| >> || 右ビットシフト
|-
| & || ビット単位のAND
|-
| ^ || ビット単位のXOR
|-
| <nowiki>|</nowiki> || ビット単位のOR
|-
| <=<br>>=<br><<br>> || 大小の比較(TRUEは1、FALSEは0)
|-
| ==<br>!= || 等価または等価ではない(TRUEは1、FALSEは0)
|-
| ! || 論理否定
|-
| && || 論理的AND
|-
| <nowiki>||</nowiki> || 論理的OR
|-
| <式1> ? <式2> : <式3> || 三項演算(<式1>がTRUEならば<式2>、<式1>がFALSEなら<式3>を評価する)
|}
</center>
<br>
この他に、以下のような代入演算子を使用できる。<br>
* =
* *=
* /=
* %=
* +=
* -=
* <<=
* >>=
* &=
* ^=
* |=
<br>
<br>
==== ランダムな数値の取得 ====
==== ランダムな数値の取得 ====
Bashのシェル変数$RANDOMを参照すると、0~32767の範囲のランダムな整数を取得することができる。<br>
Bashのシェル変数$RANDOMを参照すると、0~32767の範囲のランダムな整数を取得することができる。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/bash
   
   
  echo $RANDOM
  echo $RANDOM
  </source>
  </syntaxhighlight>
<br>
<br>
  # 出力
  # 出力
  27591
  27591
<br>
<br>
== 文字列の連結 ==
== 文字列の連結 ==
複数の変数を連結するには、以下のように続けて記述する。<br>
複数の変数を連結するには、以下のように続けて記述する。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/sh
  #!/bin/sh
   
   
134行目: 365行目:
   
   
  echo $STR
  echo $STR
  </source>
  </syntaxhighlight>
<br>
<br>
また、以下のように変数を{}で括る。<br>
また、以下のように変数を{}で括る。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/sh
  #!/bin/sh
   
   
144行目: 375行目:
   
   
  echo $STR
  echo $STR
  </source>
  </syntaxhighlight>
<br><br>
 
== 文字列の長さの取得 ==
変数に代入されている文字列の長さを取得するには、以下の2つの方法がある。<br>
<syntaxhighlight lang="sh">
echo ${#変数名}
# または
echo "#変数名"
expr length "変数名"
# または
expr length "文字列"
</syntaxhighlight>
<br><br>
<br><br>


154行目: 398行目:
<br>
<br>
以下の例では、lsコマンドの実行結果を変数FILESに代入して、echoで出力している。<br>
以下の例では、lsコマンドの実行結果を変数FILESに代入して、echoで出力している。<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/sh
  #!/bin/sh
   
   
  FILES=$(ls)
  FILES=$(ls)
  echo "$FILES"
  echo "$FILES"
  </source>
  </syntaxhighlight>
または<br>
または<br>
  <source lang="sh">
  <syntaxhighlight lang="sh">
  #!/bin/sh
  #!/bin/sh
   
   
  FILES=`ls`
  FILES=`ls`
  echo "$FILES"
  echo "$FILES"
  </source>
  </syntaxhighlight>
<br><br>
<br><br>
== 環境変数 ==
環境変数とは、システム全体の動作に関連する値が設定されている(もしくはユーザが任意で設定する)変数であり、<br>
環境変数として設定されている変数名とその値は<code>env</code>コマンドで確認できる。<br>
<center>
{| class="wikitable" | style="background-color:#fefefe;"
|-
! style="background-color:#66CCFF;" | 特殊変数名
! style="background-color:#66CCFF;" | 自動的に設定される値
|-
| $? || 直前に実行されたコマンドの終了ステータスが設定される変数。<br>シェルスクリプトでは、<code>exit</code>コマンドに与えた引数が終了ステータスとなる。<br><br>例えば、<code>exit 2</code>と記述する場合、そのシェルスクリプトの終了ステータスは2となる。<br>また、関数の<code>return</code>の場合も同様に、指定した引数がその関数の終了ステータスとなる。
|-
| $! || バックグラウンドで実行されたコマンドのプロセスIDが設定される変数。<br><code>sleep 100 &</code>のように<code>&</code>を付加してバックグラウンドで実行する時、<br>特殊変数$!には、sleepコマンドのPID(プロセスID)がセットされる。
|-
| $- || setコマンドで設定されたフラグまたはシェルの起動時に指定されたフラグの一覧が設定される変数。
|-
| $$ || コマンド自身のPID(プロセスID)が設定される変数。<br><br>例えば、シェルスクリプト内で作成するファイル名に変数$$を指定するというものがある。<br>例 : tempfile_$$.txt<br><br>同一シェルスクリプトを同時実行する場合、シェルスクリプト実行ごとに作成するファイル名を変更できるため、<br>各シェルスクリプトが同時に同一ファイルに出力することを防止できる。
|-
| $LINENO || この変数を使用している行の行番号が設定される変数。
|-
| ${PIPESTATUS[@]} || パイプで連結した各コマンドの終了ステータスが設定される配列。<br>この変数を使用することで、パイプの先頭や途中にあるコマンドの終了ステータスを参照することができる。<br><u>ただし、bashのみ使用できる。</u>
|-
| $PS1 || プロンプトに使用される文字列が設定されている環境変数。<br>この変数の値を変更することで、プロンプトの表示形式を変更することができる。
|-
| $PS2 || コマンドが複数行にわたった場合のプロンプトに使用される文字列が設定されている変数。<br>特殊変数PS1と同様に値を変更することにより、プロンプトの表示形式を変更することができる。
|-
| $PATH || コマンドが格納されているディレクトリのパスが設定されている変数。<br>コマンド実行時は、この特殊変数PATHに設定されているディレクトリからコマンドが自動的に検索される。
|-
| $TZ || タイムゾーンが設定されている変数。<br>変更することは無いと考えるが、例えば、古いUNIX環境において昨日の日付を取得する等、一時的に変更する場合がある。
|-
| $PWD || カレントディレクトリのパスが設定されている変数。<br><code>PS1='[${PWD}]$ '</code>のように特殊変数PS1に設定すると、プロンプトにカレントディレクトリが表示されるようになる。
|-
| $IFS || デリミタ(区切り文字)として使用される値が設定されている変数。<br>初期値において、タブ、スペース、改行が設定されている。<br><br>繰り返し文の値リストの区切り、<code>read</code>コマンドで取得する値の区切り等に使用される。
|}
</center>
<br>
以下の例では、環境変数SRC_ROOTが設定されているかを確認して、設定されていない場合はメッセージを出力して終了している。<br>
<code>echo</code>の出力を<code>>&2</code>とリダイレクトすると、標準エラー出力へ出力できる。
<syntaxhighlight lang="sh">
#!/bin/bash
if [ -z $SRC_ROOT ]; then
    echo 'Please set the "SRC_ROOT" environment variable and try again.' >&2
    exit -1
fi
echo 'Program continues...'
# 出力
# 設定されている場合
Program continues...
# 設定されていない場合
Please set the "SRC_ROOT" environment variable and try again.
</syntaxhighlight>
<br>
以下の例では、root権限でシェルを実行してるかどうかを判別している。<br>
<syntaxhighlight lang="sh">
#!/usr/bin/env sh
if [ "$UID" -eq "$ROOT_UID" ]; then
    # ...略
fi
</syntaxhighlight>
<br>
以下の例では、使用中のターミナルの種類を判別している。<br>
<syntaxhighlight lang="sh">
# ターミナルの種類を判別
if [[ $TERM == *"gnome"* ]]; then
    # gnome-terminalの場合
    # 何らかの処理
elif [[ $COLORTERM == "konsole" ]] || [[ $TERM == "xterm-256color" && -n "$KONSOLE_VERSION" ]]; then
    # Konsoleの場合
    # 何らかの処理
else
    # その他のターミナルの場合
    # 何らかの処理
fi
</syntaxhighlight>
<br>
<br><br>
== 変数展開機能 ==
変数展開の仕組みを利用すると、変数に格納された文字列を置換、変数の存在を確認、変数の初期値の指定等ができる。<br>
<br>
==== パターン照合演算子 ====
下表に示すように、変数展開の構文を使用すると、変数に格納された文字列の一部を置換した文字列を作成することができる。<br>
また、パターン部分において、ワイルドカード(*、?、[a-z]等)が使用できる。<br>
<center>
{| class="wikitable"
|-
! 構文 !! 意味
|-
| ${変数/パターン/置換文字列} || パターンに一致する部分を置換文字列に置き換える(1つだけ)
|-
| ${変数//パターン/置換文字列} || パターンに一致する部分を置換文字列に置き換える(すべて)
|-
| ${変数#パターン} || 先頭から最短一致でパターンに一致する部分を取り除く
|-
| ${変数##パターン} || 先頭から最長一致でパターンに一致する部分を取り除く
|-
| ${変数%パターン} || 末尾から最短一致でパターンに一致する部分を取り除く
|-
| ${変数%%パターン} || 末尾から最長一致でパターンに一致する部分を取り除く
|}
</center>
<br>
* 最初に一致する文字列のみ置換する。
<syntaxhighlight lang="sh">
# 実行
X=aaabbbccc
Y=${X/b/B}
echo $Y
# 出力
aaaBbbccc
</syntaxhighlight>
<br>
* パターンに一致する文字列を全て置換する。
<syntaxhighlight lang="sh">
# 実行
X=aaabbbccc
Y=${X//b/B}
echo $Y
# 出力
aaaBBBccc
</syntaxhighlight>
<br>
sedコマンドと同様の結果を、シェルスクリプトの機能だけで実現できていることがわかる。<br>
<syntaxhighlight lang="sh">
X=aaabbbccc
Y=$(echo $X | sed -e 's/bbb/BBB/g')
</syntaxhighlight>
<br>
* フルパスからbasenameを取り出す。
*: 以下の例では、/aaa/bbb/cccという絶対パスから、basenameのcccを抽出している。
*: */というパターンで、先頭から最長一致させて、/aaa/bbb/を取り除いている。
<syntaxhighlight lang="sh">
# 実行
X=/aaa/bbb/ccc
Y=${X##*/}
echo $Y
# 出力
ccc
</syntaxhighlight>
<br>
また、basenameを取得する場合、一般的に、basenameコマンドを使用した方が簡単である。<br>
<syntaxhighlight lang="sh">
basename $X
</syntaxhighlight>
<br>
* フルパスからdirnameを取り出す。
*: 以下の例では、/aaa/bbb/cccという絶対パスから、ディレクトリ名の/aaa/bbbを抽出している。
*: /*というパターンで、末尾から最短一致させて、/cccを取り除いている。
<syntaxhighlight lang="sh">
# 実行
X=/aaa/bbb/ccc
Y=${X%/*}
echo $Y
# 出力
/aaa/bbb
</syntaxhighlight>
<br>
また、ディレクトリ名を取得する場合、一般的に、dirnameコマンドを使用した方が簡単である。<br>
<syntaxhighlight lang="sh">
dirname $X
</syntaxhighlight>
<br>
* '#'以降のコメントを削除する。
*: #*というパターンで、末尾から最長一致させて、変数LINEの#以降の部分を削除している。
<syntaxhighlight lang="sh">
# 実行
LINE="aaa bbb # This is a comment"
LINE=${LINE%%#*}
echo $LINE
# 出力
aaa bbb
</syntaxhighlight>
<br>
==== 初期値 ====
<center>
{| class="wikitable"
|-
! 構文 !! 意味
|-
| ${変数:-word} || 変数が未定義の時、wordを返す。
|-
| ${変数:=word} || 変数が未定義の時、変数にwordを代入して返す。
|-
| ${変数:?}<br>${変数:?word} || 変数が未定義の時、エラーを表示する。
|-
| ${変数:+word} || 変数が定義されている時、wordを返す。
|}
</center>
* ${変数:-word}
*: 例えば、<code>X=${COUNT:-0}</code>と記述すると、変数<code>X</code>の値は変数<code>COUNT</code>の値が無ければ0を返す。
*: つまり、変数<code>COUNT</code>の初期値を0とみなして参照する。
*: <br>
*: この構文は、コマンドライン引数が省略された場合、初期値を設定するために使用できる。
*: 例えば、<code>FILENAME=${1:-input.txt}</code>とすると、変数<code>FILENAME</code>の値は、第1パラメータで指定された値または初期値のinput.txtとなる。
<br>
* ${変数:=word}
*: 例えば、X=${COUNT:=0}と記述すると、変数COUNTの値が無ければ、変数Xおよび変数COUNTに0を代入する。
*: ただし、変数に代入するため、コマンドライン引数や関数の引数の$1を参照する場合には、この方法は使用できない。
<br>
* ${変数:?word}
*: 例えば、以下のように記述すると、変数COUNTの値が無ければエラーを出力して終了する。
<syntaxhighlight lang="sh">
# 実行
echo ${COUNT:?}
# 出力
-bash: count: パラメータが null または設定されていません
</syntaxhighlight>
<br>
?の後ろに表示するメッセージを指定することもできる。<br>
<syntaxhighlight lang="sh">
# 実行
echo ${COUNT:?パラメータが設定されていません}
# 出力
-bash: count: パラメータが設定されていません
</syntaxhighlight>
<br>
* ${変数:+word}
*: 変数に値が代入されている場合、代わりにwordの値を返す。
*: 例えば、${COUNT:+1}は、変数COUNTが定義されていたら1と評価される。
<syntaxhighlight lang="sh">
# 実行
COUNT=9999
echo ${COUNT:+1}
# 出力
1
</syntaxhighlight>
<br>
<syntaxhighlight lang="sh">
# 実行
COUNT=9999
unset COUNT
echo ${COUNT:+1}
# 出力
何も表示されない
</syntaxhighlight>
<br>
==== 位置指定で部分文字列を抽出する ====
<center>
{| class="wikitable"
|-
! 構文 !! 意味
|-
| ${変数:offset} || offsetで指定した位置から末尾までの文字列を抽出する。
|-
| ${変数:offset:length} || offsetで指定した位置からlength分の文字列を抽出する。
|}
</center>
<br>
<syntaxhighlight lang="sh">
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE:3}
# 出力
DEFGHIJ
</syntaxhighlight>
<br>
<syntaxhighlight lang="sh">
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE:3:4}
# 出力
DEFG
</syntaxhighlight>
<br>
offsetやlength に負の値を指定して、末尾から文字列を抽出することもできる。<br>
ただし、offsetの前に1つ以上のスペースが必要である。(スペースを入れないと、${変数:-word}という形で初期値が指定されたとみなされる)<br>
<syntaxhighlight lang="sh">
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE: -3}
# 出力
HIJ
</syntaxhighlight>
<br>
<syntaxhighlight lang="sh>
# 実行
HOGE=ABCDEFGHIJ
echo ${HOGE: -5:-2}
# 出力
FGH
</syntaxhighlight>
<br><br>
{{#seo:
|title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki
|keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,Podman,電気回路,電子回路,基板,プリント基板
|description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux
|image=/resources/assets/MochiuLogo_Single_Blue.png
}}


__FORCETOC__
__FORCETOC__
[[カテゴリ:シェルスクリプト]]
[[カテゴリ:シェルスクリプト]]

2024年10月14日 (月) 10:38時点における最新版

概要



変数の定義と参照

変数へ値を代入する時は$を付けず、変数を参照するときは$を付ける。

 #!/bin/sh
 
 name=Michael        # 変数の定義
 echo Hello $name    # 変数の参照
 echo "Hello $name"  # ダブルクォーテーションは変数を展開する
 echo 'Hello $name'  # シングルクォーテーションは変数を展開しない


# 出力
Hello Michael
Hello Michael
Hello $name


未定義の変数を参照すると、空文字列と同様に扱われる。(エラーにはならない)

 #!/bin/sh
 
 echo "Hello $name !"


# 出力
Hello  !


変数の内容の一部を取得する場合は、${変数名:開始位置:長さ}と指定する。
なお、先頭の開始位置は0である。

指定した文字列までを削除する場合、${変数名#文字列}と指定する。
文字列を後ろから削除する場合、${変数名%文字列}と指定する。
また、文字列の指定には、ワイルドカード*が使用できる。

以下の例では、(1)環境変数LANGの0文字目から5文字分のみ取得、(2).(ドット)文字までを削除、(3).(ドット)文字以降を削除を行っている。
なお、操作を指定せず${変数名}とする場合、$変数名と同義になる。

 #! /bin/bash
 
 echo "$LANG"		# 環境変数LANGの内容を表示
 echo "${LANG:0:5}"	# (1) LANGの0文字目から5文字分のみ表示
 echo "${LANG#*.}"	# (2) .文字までを削除
 echo "${LANG%.*}"	# (3) .文字以降を削除


# 出力
ja_JP.utf8     # 環境変数LANGの内容
ja_JP          # ${LANG:0:5}の結果
utf8           # ${LANG#*.}の結果
ja_JP          # ${LANG%.*}の結果


下表に、主な変数の操作を示す。

指定方法 操作内容
${変数名:開始位置:長さ} 開始位置から指定した長さ分の文字列を切り出す
${変数名#パターン}
${変数名##パターン}
パターン部分(前方一致)を削除する。
#の場合は最短一致、##の場合は最長一致となる。
${変数名%文字列}
${変数名%%文字列}
パターン部分(後方一致)を削除する。
%の場合は最短一致、%%の場合は最長一致となる。
${変数名:-文字列} 変数の内容を取得する。
変数がセットされていない場合、指定した文字列を返す。
${変数名:=文字列} 変数の内容を取得する。
変数がセットされていない場合、指定した文字列を変数に代入して返す。
${#変数名} 変数の文字数を取得する。(配列の場合は要素数)


下表に、その他の文字列の操作を示す。

指定方法 操作内容
${@:2} 2つ目以降の引数を取得する。
${変数名:-文字列} "変数名"が未定義またはNULLの場合、"文字列"が代入される。
${変数名:=文字列} "変数名"が未定義またはNULLの場合、"文字列"が代入される。
${変数名:?文字列} "変数名"が未定義またはNULLの場合、"文字列"とエラーを出力して終了する。
${変数名:+文字列} "変数名"が未定義またはNULLの場合はNULLを代入して、それ以外の場合は"文字列"を代入する。
${変数名%文字列} 最短の接尾語を取り除く。
例えば、拡張子名を削除する時に使用する。
${変数名%%文字列} 最長の接尾語を取り除く。
${変数名#文字列} 最短の接頭語を取り除く。
例えば、ディレクトリのパス名から文字列$HOMEを削除する時に使用する。
${変数名##文字列} 最長の接頭語を取り除く。
例えば、ディレクトリのパス名から任意の文字列を削除する時に使用する。
$'文字列' Bashのみ使用可能。
例えば、echo 'a\te';と記述する場合はa\teと出力されるが、
echo $'a\te'と記述する場合はa eと出力される。
\UhhhhhhhhとUnicode(ISO/IEC 10646 )がある。


Shell Parameter Expansion(:)の有無により、変数が定義されているかどうか、および、値がNULLかどうかで動作が変わる。

指定方法 変数が定義されており値がNULLではない場合 変数が定義されており値がNULLの場合 変数が未定義の場合
${変数名:-文字列} 既存の値を返す。 "文字列"を返す。 "文字列"を返す。
${変数名-文字列} 既存の値を返す。 NULLを返す。 "文字列"を返す。
${変数名:=文字列} 既存の値を返す。 "文字列"を代入する。 "文字列"を代入する。
${変数名=文字列} 既存の値を返す。 NULLを返す。 "文字列"を代入する。
${変数名:?文字列} 既存の値を返す。 エラーを出力して終了する。 エラーを出力して終了する。
${変数名?文字列} 既存の値を返す。 NULLを返す。 エラーを出力して終了する。
${変数名:+文字列} "文字列"を返す。 NULLを返す。 NULLを返す。
${変数名+文字列} "文字列"を返す。 "文字列"を返す。 NULLを返す。


以下に、接尾語および接頭語を示す。

 #!/usr/bin/env bash
 
 hoge="${HOME}/hoge/bake/file.c"
 
 echo 'original'
 echo $hoge
 echo ''
 
 echo '${parameter%word}'
 echo ${hoge%.c}.o
 echo ''
 
 echo '${parameter%%word}'
 echo ${hoge%%file.c}new_file.o
 echo ''
 
 echo '${parameter#word}'
 echo ${hoge#$HOME}
 echo ''
 
 echo '${parameter##word}'
 echo ${hoge##*/}


# 出力
original
/Users/yasui/hoge/bake/file.c

${parameter%word}
/Users/yasui/hoge/bake/file.o

${parameter%%word}
/Users/yasui/hoge/bake/new_file.o

${parameter#word}
/hoge/bake/file.c

${parameter##word}
file.c



定数

以下のように実行すると、指定した変数や関数に対する代入、unsetができなくなる。

 readonly var      # 変数varをreadonlyにする
 readonly -a arr   # 配列arrをreadonlyにする
 readonly -f func  # 関数funcをreadonlyにする


以下のように、変数の定義と同時にreadonlyを指定することも可能である。

 readonly USERNAME="Mike"


以下の例では、変数MAX_SIZEを100で初期化した後、200という値を代入しようとしている。
変数MAX_SIZEは定数化されているので、代入しようとした場合はエラーになる。

 #!/bin/bash
 
 readonly MAX_SIZE=100
 MAX_SIZE=200


# 出力
./sample.sh: 行 4: MAX_SIZE: 読み取り専用の変数です



変数の値の確認

test[ ... ]で使用できる演算子には、以下のようなものがある。

  • -z 文字列
    文字列の長さが0の場合に真
  • -n 文字列
    文字列の長さが0でない場合に真


変数名にダブルクォーテーションを付けて値を展開して、上記の演算子でその文字列の長さをチェックすることにより、
変数に値が代入されている(または、代入されていない)ことを確認することができる。

変数に値が代入されていることを確認する

以下の例では、変数NAMEの値がセットされているか調べている。

 #!/bin/bash
 
 if [ -n "$NAME" ]; then
    echo $NAME
 fi


変数に値が代入されていないことを確認する

以下の例では、変数NAMEの値がセットされていないか調べている。

 #!/bin/bash
 
 if [ -z "$NAME" ]; then
    echo 'NAME is not set'
 fi


# 出力
NAME is not set



数値の演算

加算 / 減算

変数の値に対して、加算および減算を行うには以下のように記述する。

 #!/bin/bash
 
 val=100
 let val=$val+200
 echo $val

または

 #!/bin/bash
 
 val=100
 val=$(($val+200))
 echo $val


# 出力
300


 #! /bin/bash
 
 VALUE1="100"
 VALUE2="200"
 
 expr "$VALE1" "+" "$VALUE2"
 # または
 expr $VALUE1 + $VALUE2
 # または
 VALUE3=`expr "$str1" "+" "$str2"`
 echo "$VALUE3"


# 出力
300
300
300


整数の演算では、exprコマンドまたはletコマンドを使用するが、
実数を演算では、bcコマンドを使用する。
また、bcコマンドも制御構文を使用したスクリプト処理が可能である。

 #! /bin/bash
 
 VALUE1=10.5
 VALUE2=3.2
 
 echo $VALUE1 + $VALUE2 | bc
 
 ANS=`echo $VALUE1*$VALUE2 | bc`
 echo $ANS


下表に、letコマンドで使用できる演算子を示す。(四則演算は省略)

演算子 説明
<変数名>++
<変数名>--
変数を評価した後でインクリメントまたはデクリメントする。
++<変数名>
--<変数名>
変数をインクリメントしてから評価する、変数をデクリメントしてから評価する
** 累乗
% 剰余
~ ビット単位の否定
<< 左ビットシフト
>> 右ビットシフト
& ビット単位のAND
^ ビット単位のXOR
| ビット単位のOR
<=
>=
<
>
大小の比較(TRUEは1、FALSEは0)
==
!=
等価または等価ではない(TRUEは1、FALSEは0)
! 論理否定
&& 論理的AND
|| 論理的OR
<式1> ? <式2> : <式3> 三項演算(<式1>がTRUEならば<式2>、<式1>がFALSEなら<式3>を評価する)


この他に、以下のような代入演算子を使用できる。

  • =
  • *=
  • /=
  • %=
  • +=
  • -=
  • <<=
  • >>=
  • &=
  • ^=
  • |=


ランダムな数値の取得

Bashのシェル変数$RANDOMを参照すると、0~32767の範囲のランダムな整数を取得することができる。

 #!/bin/bash
 
 echo $RANDOM


# 出力
27591


文字列の連結

複数の変数を連結するには、以下のように続けて記述する。

 #!/bin/sh
 
 STR1="Shell script"
 STR2="is intersting!"
 
 STR=$STR1$STR2
 
 echo $STR


また、以下のように変数を{}で括る。

 #!/bin/sh
 
 STR1="Shell script"
 STR="${STR1} is intersting!!"
 
 echo $STR



文字列の長さの取得

変数に代入されている文字列の長さを取得するには、以下の2つの方法がある。

 echo ${#変数名}
 # または
 echo "#変数名"
 
 expr length "変数名"
 # または
 expr length "文字列"



コマンドの実行結果を変数に代入する

lsgrepfind等のコマンドの実行結果を変数に代入するには、以下のように記述する。

変数=$(コマンド)
   または
変数=`コマンド`


以下の例では、lsコマンドの実行結果を変数FILESに代入して、echoで出力している。

 #!/bin/sh
 
 FILES=$(ls)
 echo "$FILES"

または

 #!/bin/sh
 
 FILES=`ls`
 echo "$FILES"



環境変数

環境変数とは、システム全体の動作に関連する値が設定されている(もしくはユーザが任意で設定する)変数であり、
環境変数として設定されている変数名とその値はenvコマンドで確認できる。

特殊変数名 自動的に設定される値
$? 直前に実行されたコマンドの終了ステータスが設定される変数。
シェルスクリプトでは、exitコマンドに与えた引数が終了ステータスとなる。

例えば、exit 2と記述する場合、そのシェルスクリプトの終了ステータスは2となる。
また、関数のreturnの場合も同様に、指定した引数がその関数の終了ステータスとなる。
$! バックグラウンドで実行されたコマンドのプロセスIDが設定される変数。
sleep 100 &のように&を付加してバックグラウンドで実行する時、
特殊変数$!には、sleepコマンドのPID(プロセスID)がセットされる。
$- setコマンドで設定されたフラグまたはシェルの起動時に指定されたフラグの一覧が設定される変数。
$$ コマンド自身のPID(プロセスID)が設定される変数。

例えば、シェルスクリプト内で作成するファイル名に変数$$を指定するというものがある。
例 : tempfile_$$.txt

同一シェルスクリプトを同時実行する場合、シェルスクリプト実行ごとに作成するファイル名を変更できるため、
各シェルスクリプトが同時に同一ファイルに出力することを防止できる。
$LINENO この変数を使用している行の行番号が設定される変数。
${PIPESTATUS[@]} パイプで連結した各コマンドの終了ステータスが設定される配列。
この変数を使用することで、パイプの先頭や途中にあるコマンドの終了ステータスを参照することができる。
ただし、bashのみ使用できる。
$PS1 プロンプトに使用される文字列が設定されている環境変数。
この変数の値を変更することで、プロンプトの表示形式を変更することができる。
$PS2 コマンドが複数行にわたった場合のプロンプトに使用される文字列が設定されている変数。
特殊変数PS1と同様に値を変更することにより、プロンプトの表示形式を変更することができる。
$PATH コマンドが格納されているディレクトリのパスが設定されている変数。
コマンド実行時は、この特殊変数PATHに設定されているディレクトリからコマンドが自動的に検索される。
$TZ タイムゾーンが設定されている変数。
変更することは無いと考えるが、例えば、古いUNIX環境において昨日の日付を取得する等、一時的に変更する場合がある。
$PWD カレントディレクトリのパスが設定されている変数。
PS1='[${PWD}]$ 'のように特殊変数PS1に設定すると、プロンプトにカレントディレクトリが表示されるようになる。
$IFS デリミタ(区切り文字)として使用される値が設定されている変数。
初期値において、タブ、スペース、改行が設定されている。

繰り返し文の値リストの区切り、readコマンドで取得する値の区切り等に使用される。


以下の例では、環境変数SRC_ROOTが設定されているかを確認して、設定されていない場合はメッセージを出力して終了している。
echoの出力を>&2とリダイレクトすると、標準エラー出力へ出力できる。

 #!/bin/bash
 
 if [ -z $SRC_ROOT ]; then
    echo 'Please set the "SRC_ROOT" environment variable and try again.' >&2
    exit -1
 fi
 
 echo 'Program continues...'
 
 # 出力
 # 設定されている場合
 Program continues...
 # 設定されていない場合
 Please set the "SRC_ROOT" environment variable and try again.


以下の例では、root権限でシェルを実行してるかどうかを判別している。

 #!/usr/bin/env sh
 
 if [ "$UID" -eq "$ROOT_UID" ]; then
    # ...略
 fi


以下の例では、使用中のターミナルの種類を判別している。

 # ターミナルの種類を判別
 if [[ $TERM == *"gnome"* ]]; then
    # gnome-terminalの場合
    # 何らかの処理
 elif [[ $COLORTERM == "konsole" ]] || [[ $TERM == "xterm-256color" && -n "$KONSOLE_VERSION" ]]; then
    # Konsoleの場合
    # 何らかの処理
 else
    # その他のターミナルの場合
    # 何らかの処理
 fi




変数展開機能

変数展開の仕組みを利用すると、変数に格納された文字列を置換、変数の存在を確認、変数の初期値の指定等ができる。

パターン照合演算子

下表に示すように、変数展開の構文を使用すると、変数に格納された文字列の一部を置換した文字列を作成することができる。
また、パターン部分において、ワイルドカード(*、?、[a-z]等)が使用できる。

構文 意味
${変数/パターン/置換文字列} パターンに一致する部分を置換文字列に置き換える(1つだけ)
${変数//パターン/置換文字列} パターンに一致する部分を置換文字列に置き換える(すべて)
${変数#パターン} 先頭から最短一致でパターンに一致する部分を取り除く
${変数##パターン} 先頭から最長一致でパターンに一致する部分を取り除く
${変数%パターン} 末尾から最短一致でパターンに一致する部分を取り除く
${変数%%パターン} 末尾から最長一致でパターンに一致する部分を取り除く


  • 最初に一致する文字列のみ置換する。
 # 実行
 X=aaabbbccc
 Y=${X/b/B}
 echo $Y
 
 # 出力
 aaaBbbccc


  • パターンに一致する文字列を全て置換する。
 # 実行
 X=aaabbbccc
 Y=${X//b/B}
 echo $Y
 
 # 出力
 aaaBBBccc


sedコマンドと同様の結果を、シェルスクリプトの機能だけで実現できていることがわかる。

 X=aaabbbccc
 Y=$(echo $X | sed -e 's/bbb/BBB/g')


  • フルパスからbasenameを取り出す。
    以下の例では、/aaa/bbb/cccという絶対パスから、basenameのcccを抽出している。
    */というパターンで、先頭から最長一致させて、/aaa/bbb/を取り除いている。
 # 実行
 X=/aaa/bbb/ccc
 Y=${X##*/}
 echo $Y
 
 # 出力
 ccc


また、basenameを取得する場合、一般的に、basenameコマンドを使用した方が簡単である。

 basename $X


  • フルパスからdirnameを取り出す。
    以下の例では、/aaa/bbb/cccという絶対パスから、ディレクトリ名の/aaa/bbbを抽出している。
    /*というパターンで、末尾から最短一致させて、/cccを取り除いている。
 # 実行
 X=/aaa/bbb/ccc
 Y=${X%/*}
 echo $Y
 
 # 出力
 /aaa/bbb


また、ディレクトリ名を取得する場合、一般的に、dirnameコマンドを使用した方が簡単である。

 dirname $X


  • '#'以降のコメントを削除する。
    #*というパターンで、末尾から最長一致させて、変数LINEの#以降の部分を削除している。
 # 実行
 LINE="aaa bbb # This is a comment"
 LINE=${LINE%%#*}
 echo $LINE
 
 # 出力
 aaa bbb


初期値

構文 意味
${変数:-word} 変数が未定義の時、wordを返す。
${変数:=word} 変数が未定義の時、変数にwordを代入して返す。
${変数:?}
${変数:?word}
変数が未定義の時、エラーを表示する。
${変数:+word} 変数が定義されている時、wordを返す。
  • ${変数:-word}
    例えば、X=${COUNT:-0}と記述すると、変数Xの値は変数COUNTの値が無ければ0を返す。
    つまり、変数COUNTの初期値を0とみなして参照する。

    この構文は、コマンドライン引数が省略された場合、初期値を設定するために使用できる。
    例えば、FILENAME=${1:-input.txt}とすると、変数FILENAMEの値は、第1パラメータで指定された値または初期値のinput.txtとなる。


  • ${変数:=word}
    例えば、X=${COUNT:=0}と記述すると、変数COUNTの値が無ければ、変数Xおよび変数COUNTに0を代入する。
    ただし、変数に代入するため、コマンドライン引数や関数の引数の$1を参照する場合には、この方法は使用できない。


  • ${変数:?word}
    例えば、以下のように記述すると、変数COUNTの値が無ければエラーを出力して終了する。
 # 実行
 echo ${COUNT:?}
 
 # 出力
 -bash: count: パラメータが null または設定されていません


?の後ろに表示するメッセージを指定することもできる。

 # 実行
 echo ${COUNT:?パラメータが設定されていません}
 
 # 出力
 -bash: count: パラメータが設定されていません


  • ${変数:+word}
    変数に値が代入されている場合、代わりにwordの値を返す。
    例えば、${COUNT:+1}は、変数COUNTが定義されていたら1と評価される。
 # 実行
 COUNT=9999
 echo ${COUNT:+1}
 
 # 出力
 1


 # 実行
 COUNT=9999
 unset COUNT
 echo ${COUNT:+1}
 
 # 出力
 何も表示されない


位置指定で部分文字列を抽出する

構文 意味
${変数:offset} offsetで指定した位置から末尾までの文字列を抽出する。
${変数:offset:length} offsetで指定した位置からlength分の文字列を抽出する。


 # 実行
 HOGE=ABCDEFGHIJ
 echo ${HOGE:3}
 
 # 出力
 DEFGHIJ


 # 実行
 HOGE=ABCDEFGHIJ
 echo ${HOGE:3:4}
 
 # 出力
 DEFG


offsetやlength に負の値を指定して、末尾から文字列を抽出することもできる。
ただし、offsetの前に1つ以上のスペースが必要である。(スペースを入れないと、${変数:-word}という形で初期値が指定されたとみなされる)

 # 実行
 HOGE=ABCDEFGHIJ
 echo ${HOGE: -3}
 
 # 出力
 HIJ


 # 実行
 HOGE=ABCDEFGHIJ
 echo ${HOGE: -5:-2}
 
 # 出力
 FGH