シェルでは、次のコマンドを問題なく実行します。
ls-al
!ls
フラグls
付きのファイルもリストするための 2 番目の呼び出し。-al
しかし、上記のスクリプトを bash スクリプトに入れると、クレームがスローされ、
!ls, command not found.
スクリプトで同じ効果を実現する方法は?
スクリプトでコマンド履歴と ! スタイルの履歴展開の両方を有効にする必要があります (非対話型シェルではデフォルトでどちらも無効になっています)。
set -o history
set -o histexpand
展開されたコマンドは、対話型シェルと同様に、標準エラーにもエコーされます。histverify
シェル オプション ( )をオンにすることでこれを防ぐことができますshopt -s histverify
が、非対話型シェルでは、履歴の展開が null-op になるようです。
ええと、私はこれも機能させたかったので、このset -o history ; set -o histexpand
方法はでは機能しないことをみんなに伝えなければなりませんbash 4.x
。とにかく、これを達成するためのより良い方法があるため、そこで使用することを意図していません。
まず第一に、スクリプトで実行したいだけのかなり些細な例です: ( 4.x 以降のみ)history
bash
#!/bin/bash -i
history
簡単な答え:うまくいきます!!
新しい-i
オプション spanking はinteractiveの略で、動作しhistory
ます。しかし、何の目的で?
OP からの Michael H. のコメントを引用し
ます。「これを有効にすることはできますが、これはプログラミングの実践としては不適切です。スクリプト (...) が理解しにくくなります。デフォルトで無効になっているのには理由があります。なぜこれをしたいですか?」
はい、なぜですか?これの深い意味は何ですか?それについては、次のセクションで説明します。
私のhistory
バッファーは巨大になりましたが、それらの行のいくつかはスクリプトのワンライナーであり、毎回再入力したくありません。しかし、場合によっては、これらの行を少し変更したいこともあります。これは、以前は合計で 2 つしか必要としなかったのに対し、おそらく 3 番目のパラメーターを指定したいからです。したがって、 4.0+ 機能を使用してを呼び出す理想的な方法は次のとおりです。bash
history
$ history
(...)
<lots of lines>
(...)
1234 while IFS='whatever' read [[ $whatever -lt max ]]; do ... ; done < <(workfile.fil)
<25 more lines>
したがって、履歴からの1234は、まさに私たちが望む行です。確かに、マウスを持ってそこに移動し、行全体を一次バッファに入れることはできますか? しかし、私たちは *NIX を使用しています。これが、以下の小さなスクリプトを書いた理由です。繰り返しますが、これはbash
4.0 以降専用です (ただしbash
、前述のものを使用して 3.x およびそれ以前のバージョンに適応する可能性がありますset -o ...
...)
#!/bin/bash -i
[[ $1 == "" ]] || history | grep "^\s*$1" |
awk '{for (i=2; i<=NF; i++) printf $i" "}' | tr '\n' '\0'
たとえば、これを保存するとxselauto.sh
、呼び出すことができます
$ ./xselauto.sh 1234
history
行番号 1234の内容がプライマリ バッファに格納され、再利用の準備が整います。それでも誰かが「これには目的がありません AFAICS」または「誰がこの機能を必要とするでしょうか?」と言う場合。- わかりました、気にしません。しかし、複雑な行を毎回再入力するのが面倒なので、この機能なしでは生きていきたくありません。そして、履歴からマークされた行ごとにマウスに触れたくありません.TBH. これは、そのxsel
ために書かれたものです。
ところで、パイプの一部は、コマンドが実行されtr
ないようにするダーティハックです。「危険な」コマンドの場合、ユーザーがキーを押して実行する前に、常にユーザーに見えるようにしておくことが非常に重要です。省略しても構いませんが・・・注意されました。Enter
PS このスクリプトレットは実際には回避策!1234
であり、bash シェルでの入力をシミュレートします。スクリプトで直接!
作業を行うことはできなかったので(履歴行 1234の内容を明らかにすることはできませんでした)、コピーしたい行を ing するだけで問題を回避しました。echo
grep
履歴の拡張は、スクリプト言語の一部ではなく、シェルのインタラクティブなコマンドライン編集機能の一部です。スクリプトのコンテキストでは一般的に使用できませんが、(疑似)人間のオペレーターと対話する場合にのみ使用できます。(疑似とはexpect
、特定のオペレーターが人間以下である可能性があることを意味するのではなく、一般的に人間の行動を演じようとする他のキーストローク反復自動化ツールのようなもので動作させることができることを意味します)。