web-dev-qa-db-ja.com

Bash拡張動作

Readline関数Shell-expand-linealias-expand-lineをいじっていました。 ドキュメント から:

Shell-expand-lineシェルと同じように行を展開します。これは、エイリアスと履歴の展開、およびすべてのシェルワードの展開を実行します( シェルの展開を参照 )。

これについての私の理解は、Shell-expand-lineが実際の実行の前にbashが行うすべての置換と展開を実行するということです。

不自然な例がこれをサポートしているようです:

$ NAME="Adam"
$ alias ec='echo'
$ ec $NAME

関数Shell-expand-lineを実行すると、前のコマンドは$ echo Adamに展開されます。

私の混乱が始まるのは、次の例です。

$ alias cdspace='cd ~/path\ with\ spaces'
$ cdspace

Shell-expand-lineを実行するかどうかの私の理解に基づいて、コマンドは$ cd /Users/Adam/path\ with\ spacesに拡張されます。ただし、実際には$ cd ~/path with spacesに展開されます。 cdspaceをそのまま、またはalias-expand-lineで実行すると期待どおりに動作しますが、Shell-expand-lineで展開すると、実行が失敗します。

Shell Expansions のサブセクション Quote Removal はこれに対処します:

上記の展開の後、上記の展開のいずれかによるものではない、文字「\」、「 '」、および「」の引用符で囲まれていないすべての出現が削除されます。

したがって、引用符で囲まれていないバックスラッシュは常に削除されるようです。これをテストするには、$ cd ~/path\ with\ spacesを手動で入力してShell-expand-lineを実行すると、コマンドが$ cd ~/path with spacesに更新されます。さらに、$ cd ~/path\\ with\\ spacesと入力してからShell-expand-lineを2回実行すると、1組のバックスラッシュが削除されます。

私の予想では、Shell-expand-lineは、bashによって最終的に内部的に解決される行まで完全に拡張しますが、複数回実行する必要があるため、そうではないようです。

私が最終的に混乱しているのは、_ Shell Expansionsのドキュメント を理解しているように、$ cd ~/path\ with\ spacesが正しく実行される方法です。最終的には$ cd ~/path with spacesに解決されます。

3
atommclain

ここではbashのドキュメントは不明確だと思います。別のコメントで述べたように、Shell-expand-lineドキュメントは、チルダ展開が明確に行われていない場合にallシェル展開が実行されることを示唆しています。

さらに、引用の削除手順では、最初のセットがパターンマッチングされた後も残っている引用符で囲まれていないバックスラッシュは削除されません。これは、3.5.9( )とは異なり、https://www.gnu.org/savannah-checkouts/ gnu/bash/manual/bash.html#Quote-Removal )が示します。

とはいえ、私はそうは思いませんShell-expand-lineは、シェルから実行できるコマンドを生成することを目的としています。入力がalreadyにトークン化されていることを前提とするすべてのシェル拡張を実行しているため、パターンマッチングステップではバックスラッシュが削除され、以前にエスケープされたスペースが「エスケープ解除」されます。結果の文字列を実行しようとすると、トークン化againとなり、スペースで区切られた各Wordは個別のトークンとして扱われます。

1
elstongunn