「シェルスクリプトの基礎 - コマンドライン引数」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

文字列「__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…
 
(同じ利用者による、間の7版が非表示)
1行目: 1行目:
== 概要 ==
== 概要 ==
コマンドライン引数とは、シェルスクリプト実行時に渡される値のことである。<br>
コマンドライン引数とは、シェルスクリプト実行時に渡される値のことである。<br>
引数は実行時にシェルスクリプト内で参照され、シェルスクリプトの実行結果に影響を与える。引数はパラメータと呼ばれることもある。<br>
<br>
引数は実行時にシェルスクリプト内で参照され、シェルスクリプトの実行結果に影響を与える。<br>
引数はパラメータと呼ばれることもある。<br>
  command 引数1 引数2 … 引数n
  command 引数1 引数2 … 引数n
<br>
<br>
34行目: 36行目:
パラメータの取得には、$1〜$9が使用できる。<br>
パラメータの取得には、$1〜$9が使用できる。<br>
10番目以降のパラメータを参照する場合は、${10}のように数値を{}で囲めば参照できる。<br>
10番目以降のパラメータを参照する場合は、${10}のように数値を{}で囲めば参照できる。<br>
  <source lang="bash">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/sh
   
   
  echo '$1 =' "$1"
  echo '$1 =' "$1"
  echo '$2 =' "$2"
  echo '$2 =' "$2"
  echo '$3 =' "$3"
  echo '$3 =' "$3"
  </source>
  </syntaxhighlight>
<br>
<br>
  # 実行結果
  # 実行
  ./sample.sh AAA BBB "CCC  DDD"
  ./sample.sh AAA BBB "CCC  DDD"
   
   
# 出力
  $1 = AAA
  $1 = AAA
  $2 = BBB
  $2 = BBB
50行目: 53行目:
<br>
<br>
パラメータを指定しない場合は、対応する変数は空になる。<br>
パラメータを指定しない場合は、対応する変数は空になる。<br>
  # 実行結果
  # 実行
  ./sample.sh AAA BBB
  ./sample.sh AAA BBB
   
   
# 出力
  $1 = AAA
  $1 = AAA
  $2 = BBB
  $2 = BBB
59行目: 63行目:
echoの引数として変数を渡す場合は、"$1"のようにダブルクォートで囲む癖をつける。<br>
echoの引数として変数を渡す場合は、"$1"のようにダブルクォートで囲む癖をつける。<br>
$1のようにそのまま記述すると、値として連続するスペースが含まれていた時に1つのスペースに纏められてしまう。<br>
$1のようにそのまま記述すると、値として連続するスペースが含まれていた時に1つのスペースに纏められてしまう。<br>
<br>
以下に、コマンドライン引数のを使用した応用例を示す。<br>
シェルスクリプトが2つ以上のパラメータを必要としている場合、シェルスクリプトの先頭で以下のように確認する。<br>
<syntaxhighlight lang="sh">
# 例 : 2つ以上のパラメータが必要な場合
#!/bin/bash
if [ $# -lt 2 ]; then
    echo "Usage: $(basename $0) <file1> <file2>" >&2
    exit -1
fi
</syntaxhighlight>
<br>
以下の例に、様々なコマンドライン引数の確認方法を示す。<br>
<syntaxhighlight lang="sh">
# 例 : 1つ以上のコマンドライン引数が必要な場合
#!/bin/bash
if [ ! "$1" ]; then
    echo "Usage: $(basename $1) <file>" >&2
    exit -1
fi
</syntaxhighlight>
<br>
<syntaxhighlight lang="sh">
# 例 : 1つ以上の引数が必要かつ特定のファイルが存在する場合
#!/bin/bash
# 引数の確認
if [ ! "$1" ]; then
    echo "Usage: $(basename $0) <file>" >&2
    exit -1
fi
# ファイルの存在の確認
if [ ! -f "$1" ]; then
    echo "$1 is not found" >&2
    exit -1
fi
</syntaxhighlight>
<br><br>
<br><br>


64行目: 108行目:
パラメータが指定されなかった時のために、デフォルト値を指定しておくこともできる。<br>
パラメータが指定されなかった時のために、デフォルト値を指定しておくこともできる。<br>
下記の例では、1番目、2番目、3番目のパラメータの初期値を、それぞれ、100、200、300 に設定している。<br>
下記の例では、1番目、2番目、3番目のパラメータの初期値を、それぞれ、100、200、300 に設定している。<br>
  <source lang="bash">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/sh
   
   
  echo '$1 =' "${1:-100}"
  echo '$1 =' "${1:-100}"
  echo '$2 =' "${2:-200}"
  echo '$2 =' "${2:-200}"
  echo '$3 =' "${3:-300}"
  echo '$3 =' "${3:-300}"
  </source>
  </syntaxhighlight>
<br>
<br>
  # 実行結果
  # 実行
  ./sample.sh 500
  ./sample.sh 500
   
   
# 出力
  $1 = 500
  $1 = 500
  $2 = 200
  $2 = 200
84行目: 129行目:
シェルスクリプト実行時に渡されたパラメータは、特殊変数$@を使用して参照することができる。<br>
シェルスクリプト実行時に渡されたパラメータは、特殊変数$@を使用して参照することができる。<br>
以下の例では、for文を使用して、$@の要素を1つずつ抽出して処理している。(カウンタ変数$countをインクリメントしながらループしている)<br>
以下の例では、for文を使用して、$@の要素を1つずつ抽出して処理している。(カウンタ変数$countをインクリメントしながらループしている)<br>
  <source lang="bash">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/sh
   
   
  count=1
  count=1
  for arg in "$@"; do
  for arg in "$@"
do
     echo "$count: $arg"
     echo "$count: $arg"
     let count=$count+1
     let count=$count+1
  done
  done
  </source>
  </syntaxhighlight>
<br>
<br>
  # 実行結果
  # 実行
  ./sample.sh AAA BBB CCC
  ./sample.sh AAA BBB CCC
# 出力
  1: AAA
  1: AAA
  2: BBB
  2: BBB
  3: CCC
  3: CCC
<br>
<br>
また、特殊変数の指定部分in "$@"は省略して記述することができる。<br>
また、特殊変数の指定部分<code>in "$@"</code>は省略して記述することができる。<br>
明示的にin "$@"を記述する場合は、$@の部分をダブルクォーテーションで囲むことに注意する。<br>
明示的にin "$@"を記述する場合は、$@の部分をダブルクォーテーションで囲むことに注意する。<br>
  <source lang="bash">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/sh
   
   
  count=1
  count=1
  for arg; do
  for arg
do
     echo "$count: $arg"
     echo "$count: $arg"
     let count=$count+1
     let count=$count+1
  done
  done
  </source>
  </syntaxhighlight>
<br>
<br>
===== while文を使用する方法 =====
===== while文を使用する方法 =====
119行目: 169行目:
$1はパラメータの最初の要素を参照する変数であるが、直後のshiftによってパラメータを1つずつシフトしているので、<br>
$1はパラメータの最初の要素を参照する変数であるが、直後のshiftによってパラメータを1つずつシフトしているので、<br>
結果として、全てのパラメータを順番に参照することができる。<br>
結果として、全てのパラメータを順番に参照することができる。<br>
  <source lang="bash">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/sh
   
   
  count=1
  count=1
  while [ "$#" -ge "1" ]; do
  while [ "$#" -ge "1" ]
do
     echo "$count: $1"
     echo "$count: $1"
     shift
     shift
     let count=$count+1
     let count=$count+1
  done
  done
  </source>
  </syntaxhighlight>
<br>
<br>
  # 実行結果
  # 実行
  ./sample.sh AAA BBB CCC
  ./sample.sh AAA BBB CCC
# 出力
  1: AAA
  1: AAA
  2: BBB
  2: BBB
141行目: 195行目:
$@が各パラメータを個別に保持しているのに対し、$*は全てのパラメータを結合した1つの文字列である。<br>
$@が各パラメータを個別に保持しているのに対し、$*は全てのパラメータを結合した1つの文字列である。<br>
それぞれ、ダブルクォートで囲んで参照した場合と、囲まずに参照した場合の展開方法も含めて理解する。<br>
それぞれ、ダブルクォートで囲んで参照した場合と、囲まずに参照した場合の展開方法も含めて理解する。<br>
  <source lang="bash">
  <syntaxhighlight lang="sh">
  #!/bin/bash
  #!/bin/sh
   
   
  echo '=== Pattern 1 ==='
  echo '=== Pattern 1 ==='
  for arg in "$@"; do
  for arg in "$@"
do
     echo "$arg"
     echo "$arg"
  done
  done
   
   
  echo -e '\n=== Pattern 2 ==='
  echo -e '\n=== Pattern 2 ==='
  for arg in $@; do
  for arg in $@
do
     echo "$arg"
     echo "$arg"
  done
  done
   
   
  echo -e '\n=== Pattern 3 ==='
  echo -e '\n=== Pattern 3 ==='
  for arg in "$*"; do
  for arg in "$*"
do
     echo "$arg"
     echo "$arg"
  done
  done
   
   
  echo -e '\n=== Pattern 4 ==='
  echo -e '\n=== Pattern 4 ==='
  for arg in $*; do
  for arg in $*
do
     echo "$arg"
     echo "$arg"
  done
  done
  </source>
  </syntaxhighlight>
<br>
<br>
  # 実行結果
  # 実行
  ./sample.sh "100 200" "CCC DDD"
  ./sample.sh "100 200" "CCC DDD"
   
   
# 出力
  === Pattern 1 ===
  === Pattern 1 ===
  100 200
  100 200
203行目: 262行目:
  for arg in 100 200 AAA BBB; ...
  for arg in 100 200 AAA BBB; ...
<br><br>
<br><br>
== ラッパー ==
シェルスクリプトの実行時の引数を、そのまま別のコマンドに渡す場合、<code>"$@"</code>を使用する。<br>
このような用途で記述されているシェルスクリプトのことをラッパーと呼ぶ。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
./do_command.sh "$@"
</syntaxhighlight>
<br><br>
== shiftコマンドによる引数の操作 ==
<code>shift</code>コマンドは、シェルスクリプトに渡した引数を順番に処理することができる。<br>
<br>
上記のセクションに記述した通り、シェルスクリプトに渡した引数は、$1や$2等の特殊変数として扱われる。<br>
<code>shift</code>コマンドを使用すると、この特殊変数を順番にずらすことができる。<br>
したがって、<code>shift</code>コマンドを実行すると、$2の値は$1に代入され、$3の値は$2に代入されるといった変数の値をシフトすることができる。<br>
<br>
以下の例では、<code>shift</code>コマンドを実行して$1の値を出力し続けている。<br>
<code>shift</code>コマンドにより、3つの引数が順番にシフトされている。<br>
<syntaxhighlight lang="sh">
#!/bin/sh
# $1が空になるまで繰り返し
while [ -n "$1" ]
do
    echo "param = $1"
    shift
done
# 実行
./test-shift.sh a b c
# 出力
param = a
param = b
param = c
</syntaxhighlight>
<br><br>
== コマンドライン引数の解析 : getopts ==
複雑なコマンドライン引数の指定する場合、全てのコマンドライン引数の妥当性の確認等、解析にはかなりの労力を要する。<br>
そのため、<code>getopts</code>コマンドを使用することで、コマンドライン引数の解析を容易に行うことができる。<br>
<br>
以下の例のように、コマンドライン引数の解析には、<code>while文</code>と<code>getopts</code>コマンドを組み合わせて使用する。<br>
<code>getopts</code>コマンドの第1引数には、シェルスクリプトに指定可能な引数名を指定して、その引数が値を要する場合は<code>:</code>(コロン)を付加する。<br>
第2引数には、解析に使用する任意の変数名を指定する。あくまでも変数名であるので、<code>$</code>を付ける必要はない。<br>
<br>
以下の例において、xxx.sh -a -b "BBB" -c "CCC"といったコマンドを実行する時、"BBB"および"CCC"等の値は変数<code>OPTARG</code>に代入される。<br>
<syntaxhighlight lang="sh">
#!/usr/bin/env sh
while getopts ab:c: OPT
do
    case $OPT in
      "a" )
          FLG_A="TRUE"
          ;;
      "b" )
          FLG_B="TRUE"
          VALUE_B="$OPTARG"
          ;;
      "c" )
          FLG_C="TRUE"
          VALUE_C="$OPTARG"
          ;;
    esac
done
</syntaxhighlight>
<br>
以下の例では、<code>getopts</code>コマンドを利用したシェルスクリプトを作成している。<br>
<syntaxhighlight lang="sh">
# param_getopts.shファイル
#!/usr/bin/env sh
CMDNAME=`basename $0`
while getopts ab:c: OPT
do
    case $OPT in
      "a" )
          FLG_A="TRUE"
          ;;
      "b" )
          FLG_B="TRUE"
          VALUE_B="$OPTARG"
          ;;
      "c" )
          FLG_C="TRUE"
          VALUE_C="$OPTARG"
          ;;
      * )
          echo "Usage: $CMDNAME [-a] [-b VALUE] [-c VALUE]" 1>&2
          exit 1
          ;;
    esac
done
if [ "$FLG_A" = "TRUE" ]; then
    echo '"-a"オプションが指定されました'
fi
if [ "$FLG_B" = "TRUE" ]; then
    echo '"-b"オプションが指定されました'
    echo "値は$VALUE_Bです"
fi
if [ "$FLG_C" = "TRUE" ]; then
    echo '"-c"オプションが指定されました'
    echo "値は$VALUE_Cです"
fi
exit 0
# 実行
./param_getopts.sh  # 引数の指定が無い場合、何も出力せずに終了する
./param_getopts.sh -a
./param_getopts.sh -a -b "123456"
./param_getopts.sh -ab "123456"  # -abのように複数のオプションをまとめて指定することも可能
./param_getopts.sh -a -b "123456" -c  # -cオプションに値が指定されていないためエラー
./param_getopts.sh -a -b "123456" -c "ABCDEF"
# 出力
"-a"オプションが指定されました
"-a"オプションが指定されました
"-b"オプションが指定されました
値は123456です
"-a"オプションが指定されました
"-b"オプションが指定されました
値は123456です
./param_getopts.sh: option requires an argument -- c
Usage: param_getopts.sh [-a] [-b VALUE] [-c VALUE]
"-a"オプションが指定されました
"-b"オプションが指定されました
値は123456です
"-c"オプションが指定されました
値はABCDEFです
</syntaxhighlight>
<br><br>
== getoptsコマンドとshiftコマンドの組み合わせ ==
複雑なコマンドライン引数の指定が必要なシェルスクリプトの場合、<br>
引数の解析後に不要となった引数に対して、<code>shift</code>コマンドで切り捨てることができる。<br>
<br>
以下の例では、変数<code>OPTIND</code>から1を引いた分だけ<code>shift</code>コマンドを実行することにより、不要になった引数を切り捨てている。<br>
<syntaxhighlight lang="sh">
shift $(expr $OPTIND - 1)
</syntaxhighlight>
<br>
変数<code>OPTIND</code>は、<code>getopts</code>コマンドがオプションを順番に処理するために使用するオプション位置を示すカーソルのような働きをする変数である。<br>
<code>getopts</code>コマンドの終了後は、変数<code>OPTIND</code>の値がオプションの直後を指し示しているため、<br>
この値から1減算した分だけ<code>shift</code>することにより、オプション部分を切り捨てることができる。<br>
<br>
以下の例では、シェルスクリプト内において、getopts abc OPTと記述されている場合、<code>getopts</code>コマンドの終了後の変数<code>OPTIND</code>の値は、<br>
<パラメータ>の位置を指し示している。<br>
その値から1減算して<code>shift</code>するということは、-a -b -cを切り捨てることになる。<br>
xxx.sh -a -b -c "<パラメータ>"
<br>
以下の例では、オプション部分を切り捨てるシェルスクリプトを作成している。<br>
どのようなコマンドライン引数であっても、オプション部分のみが確実に切り捨てていることが確認できる。<br>
<syntaxhighlight lang="sh">
#!/usr/bin/env sh
# -a, -b, -cオプションを指定可能とする
while getopts abc OPT
do
    # ...解析処理は省略
done
# オプション部分を切り捨てる
shift $(expr $OPTIND - 1)
# オプション部分を切り捨てたため、変数$1には先頭の引数が設定されている
echo "引数に\"$1\"が指定されました"
exit 0
# 実行
./param_optind.sh -abc "PARAMETER"
./param_optind.sh -ab "PARAMETER"
./param_optind.sh -ac "PARAMETER"
./param_optind.sh "PARAMETER"
./param_optind.sh -a -b -c "PARAMETER1" "PARAMETER2"
# 出力
引数に"PARAMETER"が指定されました
引数に"PARAMETER"が指定されました
引数に"PARAMETER"が指定されました
引数に"PARAMETER"が指定されました
引数に"PARAMETER1"が指定されました
</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__
[[カテゴリ:シェルスクリプト]]
[[カテゴリ:シェルスクリプト]]