先日の遭遇した下のエラーについて調べてみた。
$ ruby -e "puts 'Hello, World!'"
bash: !': event no found
「!」とは?
!に続く文字列に一致する最新のコマンドの再実行。
Bashでエクスクラメーションマークで始まるコマンドはどういう意味でしょうか... - Yahoo!知恵袋
Bashにはヒストリ展開という機能がある。
この機能によって、コマンド中の!fooのような文字列は、実行したことのあるfooから始まるコマンドの中で最も最近のものに置き換えられる。
[Bash] ダブルクォートで囲んだコマンド置換中で!を使うとエラーになる(例: echo "$(echo '!')") - Qiita
直近のコマンドを再実行されることが分かったので、ちょっと試してみる。
$ 'uname'
Linux
$ "arch"
x86_64
このコマンドを「!」で再実行
$ !'
'uname'
Linux
$ !"
"arch"
x86_64
なるほど
ということで
$ ruby -e "puts 'Hello, World!'"
bash: !': event no found
この原因はこのコマンド以前に「'」から始まるコマンドを実行していないから、エラーが発生したことを理解。
では、「'」から始まるコマンドがあった場合、どう処理されるのか?
$ 'uname'
Linux
$ ruby -e "puts 'Hello, World!'"
ruby -e "puts 'Hello, World'uname'"
-e:1: syntax error, unexpected tIDENTIFIER, expecting end-of-input
puts 'Hello, World'uname'
^
'uname'
が展開されて実行。そして、構文エラー
ちなみに、履歴を辿ると構文エラーのコマンドで残っている。(当然か)
$ ruby -e "puts 'Hello, World'uname'"
ただ、
$ ruby -e 'puts "Hello, World!"'
Hello, World!
こっちのパターン(!"
)で、展開されない理由が良く分からない…。
''
に囲まれていることによってエスケープされた?
おまけ
$ 'uname'
Linux
$ echo '!'
!
$ echo '"!"'
"!"
$ echo "'!'"
echo "''uname'"
''uname'
最後のコマンドの展開
"
'
!'
"
↓
"
'
'uname'
"