grep -q '^enabled$' state.txtを実行する。
一致しなかった場合だけecho DISABLEDを実行する。
state.txtは読み取り可能な通常ファイルであり、grepの実行エラーは発生しないものとする。
適切なコマンド列はどれか。
ORリストの||は、左側が0以外で終了した場合だけ右側を実行する。不一致と読み込みエラーのどちらでも実行されるため、この問題では読み取り可能なファイルを前提とする。
詳細解説
grep -q '^enabled$' state.txt && echo DISABLED一致して成功した場合にDISABLEDを表示するため条件が逆になる。
&&は一致してgrepが0を返したときにDISABLEDを表示する。読み取り可能なファイルが一致しなかったときには表示されず、必要な分岐とは逆になる。
grep -q '^enabled$' state.txt || echo DISABLED||は左側が非0で終了した場合だけ右側を実行する。
前提の下では、grepが不一致の1を返した場合だけ右へ進む。ただし||自体は1専用ではなく、ファイルがない場合の2でも右へ進む。設問の前提と演算子の一般則を分けて読む。
grep -q '^enabled$' state.txt; echo DISABLEDgrepの結果に関係なくDISABLEDを表示する。
セミコロンはgrepの結果に関係なく表示を実行する。一致したファイルでもDISABLEDが出るため、失敗例だけでは適否を判断できない。
grep -q '^enabled$' state.txt | echo DISABLEDパイプは出力を接続するもので、失敗時だけの実行条件にならない。
パイプの右側のechoもコマンドとして実行される。grep -qは通常の一致行を出力せず、echoは受け取るデータの内容で分岐しない。pipefailを有効にしても、右側を開始する条件にはならない。
実際に確かめる
一時的な検証環境で実行できる例です。
LAB_DIR=$(mktemp -d) || exit 1
(
cd "$LAB_DIR" || exit 1
printf 'enabled\n' > state.txt
grep -q '^enabled$' state.txt
printf 'match status=%s\n' "$?"
grep -q '^enabled$' state.txt || printf 'match: DISABLED\n'
printf 'disabled\n' > state.txt
grep -q '^enabled$' state.txt
printf 'no-match status=%s\n' "$?"
grep -q '^enabled$' state.txt || printf 'no-match: DISABLED\n'
grep -q '^enabled$' missing.txt 2>/dev/null
printf 'error status=%s\n' "$?"
grep -q '^enabled$' missing.txt 2>/dev/null || printf 'error: DISABLED\n'
rm -- state.txt
)
rmdir -- "$LAB_DIR"参考にした公式資料
期待される結果
match status=0
no-match status=1
no-match: DISABLED
error status=2
error: DISABLED理解のポイント
- ||の短絡評価
- grep -qの終了状態
- フォールバック処理
確認時の注意
- 確認環境: Bash 5.2 / GNU grep 3.x / GNU coreutils。新規Bashの通常設定(errexitとpipefailは無効)。読み取り可能な単一ファイルの設問と、意図的な不存在ファイルの補助例を区別する。
- 検証のmatch/no-matchは設問の前提内、missing.txtは前提外のエラーを示す補助例である。補助例だけ診断文を抑え、ホストで変わる文言より終了状態2を比較する。
- GNU grep -qは、複数入力でエラーがあっても一致行を見つけると0になる場合がある。0/1/2の説明を、その例外を無視した全入力共通の断定にはしない。
基礎のおさらい
不一致とエラーを分ける
読み取り可能な単一ファイルでは一致0と不一致1を比較できる。不存在ファイルの2でも||は実行されるので、実運用で不一致だけを扱うなら終了状態1を明示的に判定する。
元の終了状態を直後に保存する
grep || echoの全体の状態は、最後に実行したコマンドの状態になる。echoが0で終わった後の$?を、元のgrepの1と読み違えない。
パイプと条件実行
|はデータの接続、||は非0を条件とする実行の制御である。pipelineの結果を変えるpipefailは、この2つを同じ操作にはしない。