命令替换可以嵌套在变量替换中吗?


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应该是变量名,而不是字符串。

Answers:


6

不,你不能。bash和其他大多数外壳程序(除外zsh)都不允许嵌套替换。

使用zsh,您可以进行嵌套替换

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

我会接受此答案,因为它提供了一些间接证据表明不可能bash。(并且再次将我推向迁移zsh。)
Sparhawk

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.

...因为内部分配发生在修改之前,但是,如前所述,外部分配具有优先权-并且它既可以扩展为内部分配的扩展,也可以扩展为修改后的内部扩展。

当然,如果已经分配了目标参数,那么所有这些都不起作用-因此,只有首先清空该变量,您才能确定这样做……老实说,这可能是最方便的分配时间了。


变通方法+1,尽管正如您所说,这比分配变量可能更糟糕!
Sparhawk

@Sparhawk-是的,绝对更糟。无论如何,实际上并没有什么错-除了不确定性之外,没有太多收获。您可以想出一些alias间接方法来使它更方便-但是,如果您认为值得这样做,则应该设置一个函数来处理安全引用并执行带有eval或类似内容的操作。w / eval-如果您可以使命令子输出的第一个字符变为可行的扩展语法,那么您可能会更轻松得多。我知道这样的事情很容易w / xsel-需要stdin-但是xsel
mikeserv

@Sparhawk-顺便说一下,我只知道该怎么做,因为在某些情况下它可能是有用的-例如提示或here-doc扩展-在其中您无法获得当前的shell分配以其他方式应用。
mikeserv

1

如果您不想创建一个变量,那么还有其他方法可以执行字符串替换:

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

谢谢,我确实知道我可以sed代替使用它,但这是关于替换嵌套的一个更普遍的问题。
Sparhawk

@Sparhawk据我所知,没有变量就无法进行变量替换。
约翰1024,3

好的,那可能就是答案。我将让问题开放几天,以查看是否有人参考了该答案,否则接受该答案。谢谢。
Sparhawk

@Sparhawk很好。
约翰1024,3

+1,但我将接受另一个答案,因为它提供了更具体的间接证据,表明它无法在bash中使用。
Sparhawk
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.