~からBash マニュアル、セクション 6.6 エイリアス、
…常にスラム読む前に行全体を少なくとも1つ入力してください。 実装するその行のすべてのコマンド。コマンドが実行されると、エイリアスが拡張されます。読む、そんなときはしないで 処刑された。したがって、他のコマンドと同じ行に表示されるエイリアス定義は、次の入力行を読むまで適用されません。
ここで私は理解する方法を見つけようとしています。 次のうち、「入力の行全体を読んで」「該当行からコマンドを実行する」ときにシェルが何をするのですか?
結果を表示するためのコマンドと例はありますか?
- 後ろに 吹く 読む 1行全体を入力してください。
- しかし、今後 実装するこの行にコマンドがありますか?
例えば、
- 「入力の行全体を入力してください」は、複数のコマンドで構成される複合コマンドです。
- 「完全な入力ライン」は、複数の複合コマンドのパイプライン、パイプラインのリストなどでもあります。
答え1
これを理解する良い方法は、次の例を見ることです。https://stackoverflow.com/questions/38526612/bash-unable-to-set-and-use-alias-in-the-same-line
たとえば、次のコマンドを実行しようとします。
$ alias foo="echo bac" ; foo;
-bash: foo: command not found
$ foo
bac
bashは行全体を読み込み、foo
エイリアスがないため拡張されません(エイリアスは読み取ると拡張されます)。この行が実行されると、エイリアスが設定され、エラーが発生します。
答え2
あなたが引用したBashマニュアルのセクションは次のとおりです。
エイリアスは、コマンドの実行時ではなく、コマンドの読み込み時に拡張されます。したがって、他のコマンドと同じ行に表示されるエイリアス定義は、次の入力行を読むまで適用されません。
したがって、エイリアシングは、実際に行を読むことと実行することの違いを示す例の1つです!
これを明確にするために複合コマンドがあります。まずエイリアスを定義してから、それを試してみます。
alias echo=uname; echo
Bashに慣れていない人は、このコマンドの出力がLinux
(または実行しているオペレーティングシステムが何であるか)期待することができますが、実際には何も出力しません。 Bashが最初だからです。読む行をクリックしてエイリアス定義を適用します。 Bashが見るものは次のとおりです。
alias echo=uname; echo
2番目のものecho
には変換されませんuname
。これは、Bashalias echo=uname
がまだコマンドを実行していないためです。読むそれ。 Bash はその行を読んだ後、読んだ内容を実行します。したがって、以下が実行されます。
alias echo=uname; echo
(上記の通り正確に読み取られています)
と入力して、Bashがコマンドを実行したことを確認することもできますecho
。以前にエイリアスを定義したので、読み込みecho
フェーズでエイリアスを変換して Bash を実行します。uname
uname
簡単に言うと:
$ alias echo=uname; echo
$ echo
Linux
編集する:
編集、Bashが入力行を読んだ後、実際に実行する前に結果を表示する方法があるかどうか尋ねました。答えは「はい」です。しかし、日常的な使用にはあまり便利ではありません(ただし、シェルの中で何が起こっているのかを理解するのは間違いなく便利です)。
次の内容でファイルを作成します。
#!/bin/bash
shopt -s expand_aliases
trapped() {
echo "On line ${1}, Bash sees: $BASH_COMMAND"
}
trap 'trapped ${LINENO}' DEBUG
alias echo=uname; echo
echo
次にファイルを実行します。
以下は、スクリプトの仕組みの説明です。
shopt -s expand_aliases
非対話モードでも、別名を拡張するように Bash に指示します (この例のように)。- 次に関数を定義します
trapped()
。呼び出されると、この関数は現在実行中のコマンドを(引数として渡された行番号とともに)印刷します。 - 私たちはそれと呼びます
trap 'trapped ${LINENO}' DEBUG
。これはBashに「という信号を見るたびに最初にDEBUG
実行trapped ${LINENO}
します。DEBUG
これはBashが自動的に生成した信号です。簡単なコマンドを実行する前に。つまり、trapped()
コマンドが実行される前に関数が呼び出されます。 - 最後に、デモのためにいくつかのコマンドを実行します。しかし、他の何かが起こる前に実行されるトラップがあるので、
trapped()
Bashはすぐに実行される内容を印刷します。このLINENO
変数は、現在行番号を提供する Bash 組み込み変数です。
コマンドを実行せずに「実行」し、Bashが読んでいる内容を続けるには、extdebug
Bashのマニュアルのオプションを見てください。
答え3
あなたの質問はあまり明確ではありませんが、あなたの文の並置は
注文するとき読む、そんなときはしないで処刑された。
そして
いつもクソ閉じて読む前に行全体を少なくとも1つ入力してください。 実装するその行のすべてのコマンド。
質問の焦点がエイリアス拡張であることを示します。 (Bashマニュアルの抜粋を除いて、あなたの質問にエイリアスがまったく記載されていないので、「提案」と言います。)
質問の元のバージョン
Bashがその行でコマンドを実行する前に、常に入力の行全体を読み取ることをどのように証明できますか?
これを行う唯一の実際の方法は、デバッグ/監視/追跡ツールの種類を使用してシェルの内部状態を確認することです。これは少し非現実的です。 小さなペンギンの答え手動引数で手動コンテンツをサポートする方法を示します。以下は(IMO)より明確な答えのバリエーションです。
$エイリアスmyalias =日付 $エイリアスmyalias = "ls -ld"; 2017年8月4日金曜日午前3時33分33分
シェルが実行を開始する前に(2番目)、行全体を完全に読み取る必要があると言えます。なぜなら、シェルが実行されると、次のようにmyalias
実行されるからです。エイリアスが実行されるdate
とに上書きされるため、シェルは次に拡張する必要があります。myalias
ls -ld
myalias
date
alias myalias="ls -ld"
コマンドなので、その行からコマンドを実行する前に、入力行全体を読み取る必要があります。
あなたの修正された質問、
Bashが入力行全体を読み込んだ後、その行でコマンドを実行する前に結果を表示するにはどうすればよいですか?
この場合、より意味があります。コマンドラインを見たいと思います。エイリアス拡張 その行でコマンドを実行する前、つまりエイリアス拡張の結果を確認してください。私の考えでは、あなたは次のようなものを見たいと思います。
alias myalias="ls -ld"; date
私が知る限り、その出力を得る方法はありません。エイリアスが拡張された完全な行です。ただし、xtrace
(-x
)オプションは近いです。
$セット-x $エイリアスmyalias =日付 +エイリアスmyalias =日付 $エイリアスmyalias = "ls -ld"; + エイリアス 'myalias=ls -ld' +日付 ←エイリアス拡張 2017年8月4日金曜日午前3時33分42分
もちろん、これは拡張された各コマンドが実行される前にのみ出力されるため、エイリアス拡張の結果はコマンドの出力と混在します。さらに、これは次のように表示されます。みんな拡張:
$animal=猫 +動物=猫 $echo こんにちは、myalias "$animal" R* +エコこんにちは こんにちは +世界に反響を起こす 世界 +ls -ld cat 追加情報ファイル ←エイリアス拡張 ls:アクセスできません。 cat:そのファイルまたはディレクトリはありません。 -rw-r--r--2マイユーザー名マイグループ名 489 2015年2月22日読む
私たちはそれを見ることができませんls -ld "$animal" R*
。変数拡張とパス名(glob)拡張後にのみ表示できます。また、パイプでは「うまく動作」しません。
$エイリアスmyalias =日付 +エイリアスmyalias =日付 $エイリアス| +日付 ←エイリアス拡張 +od-cb 0000000 8月04、2 0 1金曜日 106162151054040101165147040060064054040062060061 0000020 7 9:4 2:1午後7時\ n 067040040071072064062072061067040120115012 0000036
トレース出力は、date
2 つの別々の行に合計を表示します。 (出力に不明な場合は、od -cb
元のコマンドラインを見て、それが実行している操作を把握する必要があります。)date | od -cb