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

时间:2009-05-27 18:20:18

标签: bash

我拥有的是:

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

这可以嵌套(或不嵌套)成一行,即单个表达式吗?

我正在尝试从脚本名称中删除路径和扩展名,以便只保留基本名称。以上两行都运行正常。我的'C'性质只是让我更加混淆这些。

15 个答案:

答案 0 :(得分:42)

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

#!/bin/bash

export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

echo ${${HELLO}WORLD}

然后不,你不能嵌套${var}表达式。 bash语法扩展器不会理解它。

但是,如果我理解你的问题,你可能会考虑使用basename命令 - 它从给定的文件名中删除路径,如果给定扩展名,也会删除它。例如,运行basename /some/path/to/script.sh .sh将返回script

答案 1 :(得分:39)

Bash支持间接扩展:

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

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

答案 2 :(得分:11)

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

例如,请考虑以下几行:

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

答案 3 :(得分:11)

以下选项对我有用:

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

输出是:

par2

答案 4 :(得分:6)

这种嵌套在bash中似乎不可行,但它适用于zsh:

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

答案 5 :(得分:6)

实际上可以使用两个步骤在bash中创建嵌套变量。

这是一个基于Tim的帖子的测试脚本,使用user1956358建议的想法。

#!/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 ”,然后搜索“ Shell参数扩展”,可以解释许多巧妙的技巧。我今天自己一直在读一些,只是失去了大约20分钟的一天,但我的剧本会变得更好......

更新:经过更多阅读后,我会根据您的初步问题提出此建议。

progname=${0##*/}

返回

bash

答案 6 :(得分:3)

${${a}}之类的表达不起作用。要解决此问题,您可以使用eval

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

输出

value

答案 7 :(得分:2)

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

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

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

这是一个简短的测试脚本:

#!/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

答案 8 :(得分:1)

basename bultin可以帮助解决这个问题,因为你在一个部分中特意分裂:

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

它并不比两线变体快,但只有一行使用内置功能。或者,使用可以执行模式嵌套的zsh / ksh。 :)

答案 9 :(得分:1)

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

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

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

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

其他答案已经偏离OP的原始问题,并专注于是否可以使用${!var}扩展表达式的结果,但遇到了{{1}的限制必须显式匹配变量名称。话虽如此,如果你用分号连接表达式,没有什么可以阻止你有一个单行答案。

var

如果你想让它看起来像一个单一的陈述,你可以将它嵌套在子壳中,即

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

一个有趣的用法是对bash函数的参数进行间接处理。然后,您可以嵌套bash函数调用以实现多级嵌套间接,因为我们可以执行嵌套命令:

这是一个表达方向的示范:

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

这是通过嵌套命令演示多级间接:

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

答案 10 :(得分:0)

如果动机是以Python的“理解”的精神“混淆”(我会说流线型)数组处理,创建一个辅助函数,按顺序执行操作。

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

你可以使用一个漂亮的单行使用结果。

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

答案 11 :(得分:0)

尽管这是一个非常古老的线程,但该设备非常适合直接或随机选择文件/目录进行处理(播放音乐,挑选电影观看或阅读书籍等)。

在bash中,我相信通常不能直接嵌套相同类型的任何两个扩展,但是如果您可以将它们与某种不同类型的扩展分开,则可以做到。

e=($(find . -maxdepth 1 -type d))
c=${2:-${e[$((RANDOM%${#e[@]}))]}}

说明:e是目录名称的数组,c是所选目录,其显式命名为$ 2,

${2:-...}  

其中...是

给出的替代随机选择
${e[$((RANDOM%${#e[@]}))]}  

$((RANDOM%...))  
bash生成的

数字除以数组e中的项数,由

给出
${#e[@]}  

产生其余部分(来自%运算符),该剩余部分成为数组e的索引

${e[...]}

因此,您有四个嵌套的扩展。

答案 12 :(得分:0)

如果按照以下所示的中间步骤进行操作,它将起作用:

export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

varname=${HELLO}WORLD
echo ${!varname}

答案 13 :(得分:0)

不嵌套,但是可以在一行中完成

没有分号(;)或换行符:

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

另一种方式:您可以使用basename

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

答案 14 :(得分:-1)

eval将允许您做您想要的事情:

export HELLO="HELLO"
export HELLOWORLD="Hello, world!"

eval echo "\${${HELLO}WORLD}"

输出:Hello, world