コマンド置換を変数置換にネストできますか?


10

コマンドを介してアクセスする特定の文字列に変数置換を使用したいと思います。たとえば、クリップボードに何かをコピーすると、次のようにアクセスできます。

$ xclip -o -selection clipboard
Here's a string I just copied.

これを変数に割り当てると、変数の置換を行うことができます。

$ var=$(xclip -o -selection clipboard)
$ echo $var
Here's a string I just copied.
$ echo ${var/copi/knott}
Here's a string I just knotted.

しかし、変数に代入せずに変数置換を行う方法はありますか?概念的には、このようなものです。

$ echo ${$(xclip -o -selection clipboard)/copi/knott}
bash: ${$(xclip -o -selection clipboard)/copi/knott}: bad substitution

この構文は、var文字列ではなく変数名である必要があるため失敗します。

回答:


6

いいえ、できません。bash他のほとんどのシェル(を除くzsh)では、入れ子の置換は許可されていません。

を使用するとzshネストされた置換を行うことができます。

$ echo ${$(echo 123)/123/456}   
456

この回答は受け入れられませんbash。これは、で不可能であるという状況証拠がいくつか提供されているためです。(そして、私をzsh。への移行に向けて再度プッシュします。)
スパーホーク2015年

2

ええ、あなたはそれを行うことができます-一種。それは本当にきれいではありません。入れ子になっているというよりはインラインにています。問題は、展開するパラメーターの値を操作する必要があることです。そのパラメーターに値がない場合は、あまり効果がありません。そのため、値拡張しながら割り当てることができ、ほとんどショートカットにはなりません。

v=; echo "${v:=${0##*["$0${v:=$(xsel -bo)}"]}${v/copi/knott}}"

$0チェーン内でparam展開を使用し、割り当てを非表示にします。ネストされた割り当て展開内で変数の値を割り当てます。外側が優先されますが、内側のものが何にでも拡張されるため、わかりにくいです。ただし、内部の拡張をサイレントにしてから変更すると、必要なものが得られます。文字列をクリップボードにコピーした後(私は持っていませんxclip-だけですxsel)、次のように出力されます:

Here's a string I just knotted.

$0ただし、省略した場合の状況は少し明確になります。

v=; echo "${v:=${v:=$(xsel -bo)}${v/copi/knott}}"

それは印刷します:

Here's a string I just copied.  Here's a string I just knotted.

...内部割り当ては変更前に行われるためですが、前述のように、外部割り当てが優先され、内部割り当ての展開変更された内部展開の両方に展開されます。

もちろん、対象となるパラメーターが既に割り当てられている場合、それはまったく機能しません-したがって、最初に変数を空にした場合にのみ確実にそれを行うことができます... 。


あなたが言うように、回避策の+1、それはおそらく変数を割り当てるよりも悪い回避策です!
Sparhawk 2015年

@Sparhawk-ええ、間違いなくもっと悪い。とにかく、それで間違いはありません。あなたはaliasそれをもう少し便利にするためにいくつかの間接を思いつくことができます-それがあなたにとってそれの価値があるなら、evalとにかく安全な引用を処理し、とにかくそれのような何かをするための関数をセットアップすべきです。w / eval-コマンドsubの出力の最初の文字を実行可能な拡張構文にできる場合-おそらく、はるかに簡単になります。私はそのようなことは簡単ですxsel-それは標準入力を必要とします-しかしxsel
mikeserv 2015年

@Sparhawk-ちなみに、それを実行する方法は知っているだけです。なぜなら、状況によっては、それが役立つ場合があるためです-プロンプトやヒアドキュメントの拡張など-現在のシェル割り当てを取得できないと、それ以外の場合は適用できません。
mikeserv 2015年

1

変数を作成したくない場合は、文字列置換を実行する他の方法があります。

$ echo $(xclip -o -selection clipboard | sed 's/copi/knott/')
Here's a string I just knotted.

ありがとう、sed代わりに使用できることは知っていましたが、置換のネストに関しては、もっと一般的な質問になるはずでした。
スパーホーク2015年

@Sparhawk私の知る限り、変数がないと変数の置換はできません。
John1024 2015年

さて、それはおそらくその時の答えです。質問を数日間開いたままにして、他の誰かが参照された回答を持っているかどうかを確認し、そうでない場合はこれを受け入れます。ありがとう。
Sparhawk 2015年

@Sparhawkとても良いです。
John1024 2015年

+1ですが、bashでは機能しないという、より具体的な状況証拠を提供するため、別の回答を受け入れます。
スパーホーク2015年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.