read コマンドはバックスラッシュをそのまま変数にセットしないので注意が必要
とある非業務なシェルスクリプトの編集中に、ShellCheck が見慣れないエラーを吐いていることに気づいた。🤔
help コマンドで -r オプションの意味を調べてみる。
read は bash のビルトインコマンドなので、man ではなく help を使うのが正しい。
$ help read read: read [-ers] [-u fd] [-t timeout] [-p prompt] [-a array] [-n nchars] [-d delim] [name ...] ...(省略) If the -r option is given, this signifies `raw' input, and backslash escaping is disabled. ...(省略)
この説明だけだともう一つピンと来ないので、さらにググって調べてみる。
※-rオプションを指定しなかった場合、入力の末尾にあるバックスラッシュは行の継続と見なされる。バックスラッシュを入力するにはそれ自体をバックスラッシュでエスケープする必要がある。
readコマンドについてメモ | OpenGroove
どうやら read コマンドはバックスラッシュをメタキャラクタの一つとして扱っていて、特に末尾に置かれる場合には行継続として扱われる仕様とのこと。確かにバックスラッシュを標準入力として与えてみても、セットされる文字列にはバックスラッシュとして含まれない。
# バックスラッシュが先頭にあるケース(無視される) $ read test \foobar $ echo $test foobar # バックスラッシュが途中にあるケース(無視される) $ read test foo\bar $ echo $test foobar # バックスラッシュが末尾にあるケース(行継続される) $ read test foobar\ > baz $ echo $test foobarbaz # バックスラッシュが2文字連続するケース(エスケープされる) $ read test foo\\bar $ echo $test foo\bar
そこで r オプションを与えると、バックスラッシュもセットされる文字列に含まれるようになる。
$ read -r test \foobar $ echo $test \foobar $ read -r test foo\bar $ echo $test foo\bar $ read -r test foobar\ $ echo $test foobar\
今回 ShellCheck で引っかかったのは、シェルスクリプト中でパスワードの入力を求める箇所だった。ここに関してはバックスラッシュを入力として与えたときこれがセットされないのは不適切なので、r オプションをつけるように修正した(つまり ShellCheck は今回も神でした)👍