我拥有的是:
progname=${0%.*}
progname=${progname##*/}
这可以嵌套(或不嵌套)成一行,即单个表达式吗?
我正在尝试从脚本名称中删除路径和扩展名,以便只保留基本名称。以上两行都运行正常。我的'C'性质只是让我更加混淆这些。
答案 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