エディターで開くのではなく、ファイルの内容をecho
'してスクリプトを作成しようとしました
echo -e "#!/bin/bash \n /usr/bin/command args" > .scripts/command
出力:
bash:!/ bin/bash:イベントが見つかりません
この奇妙な動作を bang に分離しました。
$ echo !
!
$ echo "!"
bash: !: event not found
$ echo \#!
#!
$ echo \#!/bin/bash
bash: !/bin/bash: event not found
単一引用符を使用してみてください。
echo -e '#!/bin/bash \n /usr/bin/command args' > .scripts/command
echo '#!'
echo '#!/bin/bash'
問題は、bashが!/ bin/bashの履歴を検索しているために発生しています。一重引用符を使用すると、この動作を回避できます。
!
は履歴の置換を開始します(「イベント」はコマンド履歴の行です)。たとえば、!ls
はls
を含む最後のコマンドラインに展開し、!?foo
はfoo
を含む最後のコマンドラインに展開します。特定の単語を抽出することもできます(例:!!:1
は前のコマンドの最初の単語を指します)。詳細はマニュアルをご覧ください。
この機能は、コマンドラインエディションがプリミティブだった時代の以前のコマンドをすばやく呼び出すために開発されました。最新のシェル(少なくともbashとzsh)とコピーアンドペーストでは、履歴の拡張は以前ほど便利ではありません。
histchars
変数を設定することで、履歴置換をトリガーする文字を変更できます。ヒストリ置換をめったに使用しない場合は、たとえば、 histchars='¡^'
¡
の代わりに!
が履歴の展開をトリガーするようにします。 set +o histexpand
で機能を完全にオフにすることもできます。
特定のコマンドラインで履歴の展開を無効にするには、$histchars
の3番目の文字としてspace
を使用できます。
histchars='!^ '
その後、先頭にスペースを入れてコマンドを入力すると、履歴の展開は行われません。
bash-4.3$ echo "#!/bin/bash"
bash: !/bin/bash: event not found
bash-4.3$ echo "#!/bin/bash"
#!/bin/bash
ただし、ignorespace
にコマンドラインを履歴に記録しないように指示する方法として、$HISTCONTROL
にbash
が含まれる場合は、先行スペースも使用されることに注意してください。
両方の機能を独立させたい場合は、$histchars
の3番目の文字として別の文字を選択する必要があります。コマンドの解釈方法に影響を与えないものが必要です。いくつかのオプション:
\
)の使用:\echo foo
は機能しますが、エイリアスまたはキーワードが無効になるという副作用があります。2つのキーを入力してもかまわない場合は、通常は最初の位置に表示されない任意の文字(%
、@
、?
、自分のキーを選択)を選択して、それの空のエイリアス:
histchars='!^%'
alias %=
次に、その文字、スペース、コマンドを入力します。
bash-4.3$ % echo !!
!!
(ただし、履歴の置換が無効になっているコマンドを記録することはできません。また、$histchars
のデフォルトの3番目の文字は#
であるため、コメントで履歴の拡張が行われません。変更し、プロンプトでコメントを入力する場合、!シーケンスがそこで展開される可能性があるという事実に注意する必要があります。
提案されたソリューションは、たとえば次の例では機能しません。
$ bash -c "echo 'hello World!'"
-bash: !'": event not found
$
この場合、8進数のASCIIコードを使用してbangを印刷できます。
$ bash -c "echo -e 'hello World\0041'"
hello World!
$
まだ言及されていない簡単な解決策は、変数を使用することです:
$ var='!'
$ echo -e "#${var}/bin/bash \n /usr/bin/command args" > .scripts/command
bang!
の印刷はnot文字列が引用符で囲まれていない、または単一引用符で囲まれている、またはC-String内にある場合の問題
$ echo hi\!pal 'hi!pal' $'hi!pal'
hi!pal 'hi!pal' $'hi!pal'
Histexpandが無効になっている場合も問題ではありません(shopt -ou histexpand
またはset +o histexpand
または単にset +H
。hisexpand文字を変更してbang!
を印刷しやすくすることもできます。 。
しかし、ポータブルで最も簡単な解決策は、varを使用することです。
$ var='!'
$ echo "hi${var}pal"
hi!pal