eval – コマンド文字列を評価して実行する

プロセスツリー/親子関係

eval は、与えた文字列をもう一度シェルのコマンドとして解釈して実行します。展開(変数・コマンド置換・パス名展開など)が追加で行われ、結果のコマンドが現在のシェルで走ります。
実務では、getopt の整形結果で set -- を行うときや、生成したコマンド列を最終的に実行したいときに使われます。

構文(Syntax)

eval [ARGUMENT ...]
# 引数が複数なら、スペースで連結した1つの文字列として再解釈される
# 戻り値は「再解釈後に実行された最後のコマンド」の終了ステータス

主なオプション一覧

eval 自体に一般的なオプションはありません。実用パターンを「項目」として整理します。

オプション説明使用例
(なし)文字列を再解釈して実行eval 'echo hello'
変数で組み立て変数の中身をコマンドとして実行cmd='printf "%s\n" hi'; eval "$cmd"
連結評価複数引数は連結して1文字列として評価eval echo "$USER" is "$SHELL"
getopt と併用整形した引数列を位置パラメータへ反映eval set -- "$(getopt -o ab: -l alpha,bravo: -- "$@")"
間接参照変数名を変数で受けて参照・代入(POSIX流)name=HOME; eval "echo \$$name"

実行例

生成したコマンドを実行(基本)

説明:文字列として組み立てたコマンドを実行します。
コマンド

cmd='echo "Project: $PWD"'
eval "$cmd"

出力例(例)

Project: /home/user/work

getopt と組み合わせて安全に引数を整形

説明getopt の出力を set -- に流し込み、以降の case で処理。
コマンド

OPTS_SHORT='ab:'
OPTS_LONG='alpha,bravo:'
PARSED="$(getopt -o "$OPTS_SHORT" -l "$OPTS_LONG" -n "$0" -- "$@")" || exit 2
eval set -- "$PARSED"
while true; do
  case "$1" in
    -a|--alpha) echo alpha; shift;;
    -b|--bravo) echo "b=$2"; shift 2;;
    --) shift; break;;
  esac
done

出力例(例)

alpha
b=42

変数名を変数で参照(間接参照)

説明$name が指す変数(ここでは HOME)の値を参照します。
コマンド

name=HOME
eval "echo \$$name"

出力例(例)

/home/user

危険例:入力混入で意図しない実行(やってはいけない)

説明:外部入力をそのまま eval へ渡すとコマンド注入の危険があります。
コマンド

user_input='Alice; echo HACKED'
eval "echo Hello, $user_input"

出力例(例)

Hello, Alice
HACKED

外部入力は 決して そのまま eval に渡さないでください。必要なら厳格なバリデーション・無害化や代替手法を使います。

エラー例:再解釈先が構文エラー

説明:再解釈した文字列がシェル構文として不正だとエラー終了します。
コマンド

eval 'echo $(('
echo $?

出力例(例)

bash: syntax error near unexpected token `newline'
2

関連コマンド

  • bash -c 'STRING':新しいシェルで文字列をコマンドとして実行(呼び出し元の環境を汚さない)。
  • getopt:引数列の整形に使い、eval set -- "$( ... )" で反映。
  • ${!name}(bash拡張):間接展開eval を使わず変数名から値を参照できる。
  • declare -n ref(bash拡張):名前参照で間接代入/参照を安全に実現。
  • printf -v var ...(bash拡張):文字列の安全な代入eval "var=..." の代替。
  • xargs:標準入力から受け取ったトークンを安全に引数化してコマンド実行(eval の代替になり得る)。

備考

  • セキュリティeval二重展開を起こすため、外部入力や未検証の文字列を渡すとコマンド注入が極めて起きやすいです。基本方針は「使わない」。代替(配列、間接展開、printf -vbash -cxargs)を優先してください。
  • 可搬性eval は POSIX ユーティリティで、sh 互換シェルに広く存在します。
  • クォートeval "$cmd" のように一重の引数にまとめて渡すのが原則。展開させたい内容は**$cmd 内側のクォート**で制御します。
  • 戻り値eval 自身の終了ステータスは、再解釈後に実行された最後のコマンドの終了コードです。if eval ...; then ... fi のように条件判定に使えます。
  • デバッグ:実際に何が実行されるか不安なときは、まず printf '%q\n' で可視化したり、set -x(xtrace)を一時的に有効化して確認します。

参考

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント