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