はじめに (対象読者・この記事でわかること)

この記事は、Bashスクリプトを書き始めたばかりの初心者~中級者の方を対象にしています。
「if文で数値比較しようとしたら、急に単項演算子が予期されますとか言われて意味が分からない」という経験がある方に最適です。
記事を読むことで、なぜそのエラーが出るのか、どうすれば確実に回避できるのか、そして今後同じ轍を踏まないためのコーディングルールまで、一連の流れを完全に把握できるようになります。

前提知識

  • Bashで簡単なスクリプトを書いたことがある
  • 変数に値を代入したことがある
  • if文の存在を知っている

エラーの概要:「単項演算子が予期されます」とは何か

Bashで数値比較を行おうとした際に、以下のようなエラーメッセージが出力されることがあります。

[: 単項演算子が予期されます

このメッセージは、testコマンド([ はその短縮形)が「右辺が存在しない単項演算」として解釈してしまったときに発生します。
端的に言えば「比較対象の変数が空っぽで、演算できない」という状況です。

単項演算子エラーの原因と確実な修正方法

ステップ1:最小構成でエラーを再現する

まず、エラーが出やすい最小スクリプトを用意します。

Bash
#!/usr/bin/env bash read -rp "数字を入力してください: " num if [ "$num" -eq 100 ]; then echo "100です" fi

このスクリプトを実行し、何も入力せずにEnterを押すと以下のエラーが出ます。

[: 単項演算子が予期されます

ステップ2:なぜ空文字になるとエラーになるのかを読み解く

Bashは変数の展開後、以下のように解釈します。

# $num が空の場合
[  -eq 100 ]    # ← 左辺が空なので「単項演算子が足りない」というエラーに

-eq は二項演算子なので、左右に値が必須です。左が空だと文法的に破綻します。

ステップ3:防御的に書く=クォートで囲むだけでは不十分

変数をダブルクォートで囲んでも、空文字列は空文字列なのでエラーは変わりません。

Bash
if [ "$num" -eq 100 ]; then # 空文字のままではエラー

そこで以下の二つの対策が有効です。

対策A:デフォルト値を与える

Bash
if [ "${num:-0}" -eq 100 ]; then echo "100です" fi

:-0 は「num が未設定または空なら 0 を代わりに使う」という意味です。

対策B:数値チェックを事前に行う

Bash
if [[ "$num" =~ ^[0-9]+$ && "$num" -eq 100 ]]; then echo "100です" fi

正規表現で数値であることを確認してから比較することで、空文字や文字列を排除できます。

対策C:算術展開に任せる

Bash
if (( num == 100 )); then echo "100です" fi

(( )) は数値評価専用で、空文字でも 0 として扱われるため、単項演算子エラーが起きません。

ハマった点:set -u との組み合わせ

set -u(未設定変数の参照で即終了)を有効にしていると、空チェック前にスクリプトが終了してしまうことがあります。
その場合も対策Aのデフォルト値や対策Cの算術展開が有効です。

解決策:実用例を一つにまとめる

以下は、本番で使いやすい防御的スクリプトです。

Bash
#!/usr/bin/env bash set -euo pipefail read -rp "数字を入力してください: " num # 空・数字チェック [[ "${num:-}" =~ ^[0-9]+$ ]] || { echo "数値を入力してください"; exit 1; } if (( num == 100 )); then echo "ピンポン!100です" else echo "残念、100ではありません" fi

まとめ

本記事では、「単項演算子が予期されます」というBash特有のエラーのメカニズムと、実践的な回避策を紹介しました。

  • エラーの本質は「空文字を数値比較しようとした」こと
  • デフォルト値、正規表現、算術展開の三種の神器で防げる
  • 生の [ ではなく (( )) を使うとコードがシンプルになる

これらのテクニックを身につけることで、今後シェルスクリプトを書く際に「なんでまた急に文法エラー?」という時間を大幅に削減できます。次回は、set オプションを使った堅牢スクリプトの書き方を深掘りします。

参考資料