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

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

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

$ 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文字列以外の変数名が必要なため、この構文は失敗します。

答え1

いいえ、できません。bash他のほとんどのシェル(zsh除く

それでzshあなたはできます入れ子の交換:

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

答え2

はい、そうすることができます。本当にきれいではありません。それはもっと似ています待ち行列入れ子になったより。問題は、拡張パラメータの値を操作する必要があることです。パラメーターに値がないと、多くの操作を実行できません。したがって、値を割り当てることができます。しかし、拡張すると近道ではありません。

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

$0チェーン内でパラメータ拡張を使用して隠れる分配する入れ子になった割り当て拡張内でvar値を割り当てます。外部優先 - しかし、内部的に実行されるすべてのタスクにのみ拡張されるため、話すことは困難です。しかし、内部拡張をサイレントしてから変更すると、必要なものが得られます。文字列をクリップボードにコピーした後(私はしませんでした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.

...内部割り当ては変更前に行われるため、上記のように外部割り当てが優先され、内部割り当ての拡張まで拡張されます。そして内部拡張を修正しました。

もちろん、ターゲットパラメータはすでに割り当て - したがって、変数を最初に消去した場合にのみこれを実行できます。正直に割り当てるのに最も便利な時間です。

答え3

以下は、関連付けられたパラメータ置換のために一時変数割り当てをバイパスするハッキングの例です。

declare -a values=( "4: " "#1" "#2" "#3" "#4" )
declare -A arr["VALUES"]="${values[@]}"

echo -e "Original: ${arr[@]}"

"${arr[@]#*: ?}" >&/dev/null; san="${_//#/}"

echo -e "Sanitized: $san"

説明する:

arrarray の値で連想配列を初期化しますvalues。最初の要素は値要素の数、:フィルタリングする必要があります。と#すべての値のプレフィックスが含まれます。

"${arr[@]#*: ?}" >&/dev/null

これは、最初に値を拡張して()arrまでの前のすべての項目をフィルタリングして合計結果を削除するパラメータのオーバーライドです。これにより、結果変数の割り当てが欠落して生じるエラーも抑制されます。'4: '#*: ?stdoutstderr

>&出力()を()に割り当て、両方に割り当てる2>&1略語です。stderrfd2stdoutfd1/dev/null

ここでの秘密は、bashの特別な下線_引数を使用して、前のコマンド(上記の最初の引数拡張操作と結果リダイレクト/dev/null)から破棄された結果引数を2番目の引数置換にコピーすることです。ここでは、#プレフィックス値がフィルタリングされます。

san="${_//#/}"

出力:

オリジナル: 4: #1#2#3#4

消毒:1 2 3 4

また見なさい:特殊パラメータとシェル変数

答え4

Linuxでは、ソースコマンドをパイプできます。

echo $(xclip -o -selection clipboard)/copi/knott|source /dev/stdin

それ以外のシステムでは、/dev/stdinまず一時ファイルに書き込んでから、そのファイルに書き込む必要がありますsource

関連情報