$ {var}参数扩展expression式可以嵌套在bash中吗?

我有什么是这样的:

progname=${0%.*} progname=${progname##*/} 

这可以嵌套(或不)成一行,即一个单一的expression?

我试图剥离脚本名称的path和扩展名,以便只剩下基本名称。 以上两行工作正常。 我的'C'性质正在使我更加混淆这些。

如果通过巢,你的意思是这样的:

 #!/bin/bash export HELLO="HELLO" export HELLOWORLD="Hello, world!" echo ${${HELLO}WORLD} 

那么不,你不能嵌套${var}expression式。 bash语法扩展器不能理解它。

但是,如果我理解你的问题是正确的,你可以看看使用basename命令 – 从给定的文件名剥离path,如果给定的扩展名,也将剥离。 例如,运行basename /some/path/to/script.sh .sh将返回script

Bash支持间接扩展:

 $ FOO_BAR="foobar" $ foo=FOO $ foobar=${foo}_BAR $ echo ${foobar} FOO_BAR $ echo ${!foobar} foobar 

这应该支持你正在寻找的嵌套。

一个旧线程,但也许答案是使用间接:$ {!PARAMETER}

例如,考虑以下几行:

 H="abc" PARAM="H" echo ${!PARAM} #gives abc 

这个嵌套在bash中看起来不可能,但是它在zsh中工作:

 progname=${${0%.*}##*/} 

以下选项适用于我:

  NAME="par1-par2-par3" echo $(TMP=${NAME%-*};echo ${TMP##*-}) 

输出是:

  par2 

实际上,可以使用两个步骤在bash中创build嵌套variables。

这是一个基于Tim提供的testing脚本,使用user1956358build议的思路。

 #!/bin/bash export HELLO="HELLO" export HELLOWORLD="Hello, world!" # This command does not work properly in bash echo ${${HELLO}WORLD} # However, a two-step process does work export TEMP=${HELLO}WORLD echo ${!TEMP} 

输出是:

 Hello, world! 

通过从命令行运行' info bash '来解释很多整洁的技巧,然后search' Shell Parameter Expansion '。 我今天一直在读一些自己的东西,刚刚失去了20分钟的时间,但是我的脚本将会变得更好。

更新:更多的阅读后,我build议这个替代你的第一个问题。

 progname=${0##*/} 

它返回

 bash 

bultin这个基本名字可以帮助你,因为你在一个部分特别分裂:

 user@host# var=/path/to/file.extension user@host# basename ${var%%.*} file user@host# 

它并不比双线更快,但它只是使用内置function的一条线。 或者,使用zsh / ksh可以做模式嵌套的事情。 🙂

我知道这是一个古老的线索,但这里是我的2美分。

这是一个(公认的kludgy)bash函数,它允许所需的function:

 read_var() { set | grep ^$1\\b | sed s/^$1=// } 

这是一个简短的testing脚本:

 #!/bin/bash read_var() { set | grep ^$1\\b | sed s/^$1=// } FOO=12 BAR=34 ABC_VAR=FOO DEF_VAR=BAR for a in ABC DEF; do echo $a = $(read_var $(read_var ${a}_VAR)) done 

产出如预期:

 ABC = 12 DEF = 34 

${${a}}这样的expression式不起作用。 要解决这个问题,你可以使用eval

 b=value a=b eval aval=\$$a echo $aval 

输出是

value

如果动机是用Python的“理解”的精神来“混淆”(我会说简化)数组处理,那么就创build一个帮助函数,按顺序执行这些操作。

 function fixupnames() { pre=$1 ; suf=$2 ; shift ; shift ; args=($@) args=(${args[@]/#/${pre}-}) args=(${args[@]/%/-${suf}}) echo ${args[@]} } 

你可以使用一个很好的单行结果。

 $ echo $(fixupnames ab abc def ghi) a-abc-b a-def-b a-ghi-b 

OP的原始问题有一个一行解决scheme,即剥离文件扩展名的脚本的基本名称:

 progname=$(tmp=${0%.*} ; echo ${tmp##*/}) 

这是另一个,但是,使用基地名称作弊:

 progname=$(basename ${0%.*}) 

其他答案已经摆脱了OP的原始问题,并着重讨论是否可以用${!var}扩展expression式的结果,但遇到了var必须明确地匹配variables名的限制。 话虽如此,如果用分号将expression式链接在一起,没有任何东西可以阻止你使用单引号的答案。

 ANIMAL=CAT BABYCAT=KITTEN ANSWER=$(tmp=BABY${ANIMAL} ; echo ${!tmp}) # ANSWER=KITTEN 

一个有趣的用法是对于bash函数的参数的间接工作。 然后,你可以嵌套你的bash函数调用来实现多层嵌套间接。

下面是一个expression式间接的示例:

 function deref { echo ${!1} ; } ANIMAL=CAT BABYCAT=KITTEN deref BABY${ANIMAL} # Outputs: KITTEN 

这是一个多层间接的演示:

 function deref { echo ${!1} ; } export AA=BB export BB=CC export CC=Hiya deref AA # Outputs: BB deref $(deref AA) # Outputs: CC deref $(deref $(deref AA)) # Outputs: Hiya 

eval将允许你做你想要的:

 export HELLO="HELLO" export HELLOWORLD="Hello, world!" eval echo "\${${HELLO}WORLD}" 

输出: Hello, world