A substituição do comando pode ser aninhada na substituição de variável?

7

Eu gostaria de usar a substituição de variáveis em uma string específica que eu acesse por meio de um comando. Por exemplo, se eu copiar algo na minha área de transferência, posso acessá-lo assim.

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

Se eu atribuí-lo a uma variável, então eu posso fazer uma substituição variável.

$ 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.

No entanto, existe uma maneira de fazer a substituição de variáveis sem atribuí-lo a uma variável? Conceitualmente, algo assim.

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

Esta sintaxe falha, porque var deve ser um nome de variável, não uma string.

    
por Sparhawk 11.03.2015 / 04:04

3 respostas

5

Não, você não pode. bash e a maioria dos outros shells (exceto zsh ) não permitem substituição aninhada.

Com zsh , você pode fazer substituição aninhada :

$ echo ${$(echo 123)/123/456}   
456
    
por 11.03.2015 / 04:55
2

Sim, você pode fazer isso - mais ou menos. Não é muito bonito. É mais como in-line do que aninhado. O problema é que você tem que operar no valor do parâmetro que você expande - se esse parâmetro não tiver valor, você não fará muito. Então, você pode atribuir o valor enquanto expandindo-o e dificilmente é um atalho.

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

Eu uso a expansão $0 param dentro da cadeia para ocultar a atribuição. Ele atribui o valor do var dentro de uma expansão de atribuição aninhada. O exterior tem precedência - mas porque se expandiria para qualquer coisa que seja interna, é difícil dizer. No entanto, se nós silenciarmos a expansão interna, então modificá-lo, você pode obter o que deseja. Depois de copiar sua string para minha área de transferência (não tenho xclip - apenas xsel ) imprime:

Here's a string I just knotted.

É um pouco mais claro o que está acontecendo se você deixar $0 out, embora:

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

Isso imprime:

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

... porque a atribuição interna ocorre antes da modificação, mas, como notado, a atribuição externa tem precedência - e se expande para a expansão da atribuição interna e para a expansão interna modificada .

É claro que nada disso funciona se o parâmetro alvo já está atribuído - então você só pode fazê-lo com certeza se você esvaziar a variável ... o que, honestamente, é provavelmente o momento mais conveniente para atribuí-lo depois de tudo.

    
por 11.03.2015 / 07:14
1

Se você não quiser criar uma variável, existem outras maneiras de realizar a substituição de strings:

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