15

バックグラウンド:

「監視」プログラムにアクセスできないため、設定された間隔でコマンドを実行する関数を作成しようとしています。最も基本的なものに簡略化すると、私が書こうとしている関数はrunit() { $1; }.

機能するもの:

エイリアスではないものを渡すと、これはうまく機能します。たとえば、正常にrunit "ls -l"動作します。コマンドから完全な出力を取得しますls -l

機能しないもの:

問題は、エイリアスを渡すと始まります。たとえば、設定してalias ll="ls -l"から呼び出すrunit "ll"と、 になり-bash: ll: command not foundます。

私が試したこと:

alias をハードコードするrunit() { ll; }と、正常に動作し、期待どおりの結果が得られます。


何かを見落としているような気がしますが、指を置くことはできません。
エイリアスをハードコーディングすると問題なく動作するのに、関数に渡すと失敗するのはなぜですか?
私がやろうとしていることを達成する方法はありますか?

4

3 に答える 3

8

エイリアスのbashマニュアルページの議論から(私のものを強調します):

エイリアスは、コマンドの実行時ではなく、読み取り時に展開されます。したがって、別のコマンドと同じ行にあるエイリアス定義は、入力の次の行が読み込まれるまで有効になりません。その行のエイリアス定義に続くコマンドは、新しいエイリアスの影響を受けません。この動作は、関数の実行時にも問題になります。 エイリアスは、関数定義自体が複合コマンドであるため、関数の実行時ではなく、関数定義の読み取り時に展開されます。結果として、関数で定義されたエイリアスは、その関数が実行されるまで使用できません。安全のために、エイリアス定義は常に別の行に置き、複合コマンドではエイリアスを使用しないでください。

type コマンドを使用して、関数でこの効果を確認できます。

$ run_it () { ll; }
$ type run_it

ls -l関数の本体にではなくへの呼び出しが含まれていることがわかりますll

エイリアスに関するセクションの最後の文:

ほとんどすべての目的で、エイリアスはシェル関数に取って代わられています。

その行の私の解釈は次のとおりです。エイリアスを使用したいと思う場合は、最初に関数を書いてみてください。関数が明らかに必要なことを実行できない場合を除き、エイリアスを使用しないでください。

于 2013-01-25T18:16:10.473 に答える
7

eval次のように使用できます。

$ runit() { eval $1; }
$ alias ll="ls -l"
$ runit "ll"

eval$1実行前に任意のエイリアスを展開します。

于 2015-06-23T03:14:17.590 に答える
4

この問題を解決する 1 つの方法は、エイリアスではなくシェル関数を定義することです。

ll () {
  ls -l "$@"
}

エイリアスはコマンド入力時にマクロとして展開されますが、シェル関数はコマンドの実行時に一致します。これは、シェルのマクロ プロセッサ言語が対話型の優雅さには優れているものの、実際のプログラミングを複雑にするという完璧な例です。

于 2013-01-25T18:00:18.210 に答える