ワンライナーで文字列を扱う場合は常にsingle quoteを使用したほうが安全

例えば任意の文字列を base64 エンコードするワンライナー。

echo "abcdefg$1234567" | base64

冷静になって見ればわかるんだけど、$1はシェルのビルトイン変数なので変数展開により文字列が変わってしまう(ワンライナーのときは値がないので$1 が丸々消える)。文字列がとても長い場合などに見落とす可能性があるし、コマンドにパイプしてしまうと変数展開で文字列が変わってしまった事自体がぱっとわからない。

基本的に文字列を扱う場合は single quote を基本とし、変数を含めるときだけ変えるくらいがよい。単純な文字列リテラルか変数を含んだ文字列か意識しなくて済むので、長年のクセでつい double quote してしまっていた。quote なしもダメ。変数代入する場合も同様。

FOO=abc$123 echo $FOO abc23

変数展開は行が構文解析された瞬間に行われる。なので一度代入処理を実行するとその時点で値が変わっている。

3.5 Shell Expansions

Expansion is performed on the command line after it has been split into tokens. Shell Expansions (Bash Reference Manual)

そもそも$が含まれうる文字列を扱うことは稀だけど、最近触っていた bcrypt ハッシュ関数を通した文字列は$2a$を prefix に持つ仕様でハマったのだった。Bash variables and command substitutionとかを読んでいたらハッとするようなサンプルがいくつかあったので、手癖を見直して意図しない挙動で事故らないようにしないとなと思った。

Tweet