我想对通过命令访问的特定字符串使用变量替换。例如,如果我将某些内容复制到剪贴板中,我可以像这样访问它。
$ 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
答案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"
解释:
我们使用arr
array 中的值初始化一个关联数组values
。第一个元素包含值元素的数量,后跟:
;这需要被过滤掉,以及#
所有值的前缀。
"${arr[@]#*: ?}" >&/dev/null
这是一个参数替换,首先扩展 的值arr
并过滤前面的所有内容,直到并包括'4: '
( ),丢弃和 的#*: ?
结果。这也可以抑制由于缺少结果变量分配而导致的错误。stdout
stderr
>&
是 的缩写形式2>&1
,将stderr
输出 ( fd2
) 分配给stdout
( fd1
) 并将两者都分配给/dev/null
。
现在的技巧是,使用 bash 的特殊下划线_
参数,它将上一个命令中丢弃的结果参数(上面的第一个参数扩展操作和结果重定向到/dev/null
)复制到我们的第二个参数替换中,其中#
值前缀被过滤:
san="${_//#/}"
输出:
原:4:#1#2#3#4
已消毒:1 2 3 4
另请参阅:特殊参数和 shell 变量
答案4
在 Linux 上,您可以通过管道输入 source 命令:
echo $(xclip -o -selection clipboard)/copi/knott|source /dev/stdin
对于没有 的系统/dev/stdin
,您必须先写入临时文件,然后再写入source
它。