我所拥有的是:
progname=${0%.*}
progname=${progname##*/}
可以将它嵌套(或不嵌套)到一行,即一个表达式中吗?
我正在尝试删除脚本名称的路径和扩展名,以便仅保留基本名称。以上两行工作正常。我的“ C”本质只是在驱使我更加混淆这些。
Answers:
如果是嵌套的,您的意思是这样的:
#!/bin/bash
export HELLO="HELLO"
export HELLOWORLD="Hello, world!"
echo ${${HELLO}WORLD}
那不行,您不能嵌套${var}
表达式。bash语法扩展器无法理解。
但是,如果我正确理解了您的问题,则可以考虑使用basename
命令-它会删除给定文件名中的路径,如果提供了扩展名,也会删除该路径。例如,运行basename /some/path/to/script.sh .sh
将返回script
。
bash
和ksh
。这工作:x=yyy; y=xxxyyy; echo ${y%${x}}
。我认为重要的一点是,嵌套扩展是其中一个运算符的参数。不过,我还没有看到它的记录真的很好。
echo ${${HELLO}WORLD}
说明了这种可能性。
Bash支持间接扩展:
$ FOO_BAR="foobar"
$ foo=FOO
$ foobar=${foo}_BAR
$ echo ${foobar}
FOO_BAR
$ echo ${!foobar}
foobar
这应该支持您要查找的嵌套。
以下选项对我有效:
NAME="par1-par2-par3"
echo $(TMP=${NAME%-*};echo ${TMP##*-})
输出为:
par2
echo
就将其视为par2
命令?
实际上,可以使用两个步骤在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
OP的原始问题有1行的解决方案,即文件扩展名被删除的脚本的基本名称:
progname=$(tmp=${0%.*} ; echo ${tmp##*/})
这是另一个,但是使用作弊的基本名称:
progname=$(basename ${0%.*})
其他答案已经远离OP的原始问题,而集中在是否可以仅使用扩展表达式的结果,${!var}
但是遇到了var
必须明确匹配变量名的限制。话虽如此,如果将表达式与分号链接在一起,就不会阻止您获得1-liner答案。
ANIMAL=CAT
BABYCAT=KITTEN
tmp=BABY${ANIMAL} ; ANSWER=${!tmp} # ANSWER=KITTEN
如果要使它看起来像一条语句,则可以将其嵌套在子外壳中,即
ANSWER=$( tmp=BABY${ANIMAL) ; echo ${!tmp} ) # ANSWER=KITTEN
有趣的用法是对bash函数的参数进行间接处理。然后,您可以嵌套bash函数调用以实现多层嵌套间接寻址,因为我们可以执行嵌套命令:
这是一个表达式间接的演示:
deref() { echo ${!1} ; }
ANIMAL=CAT
BABYCAT=KITTEN
deref BABY${ANIMAL} # Outputs: KITTEN
这是通过嵌套命令进行多级间接定向的演示:
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
deref()
功能如何?如果已声明,则可以使用没有临时变量的oneliner?
我知道这是一条古老的线索,但这是我的2美分。
这是一个(必不可少的)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
set | sed -n s/^$1=//p
。顺便说一句不错的黑客。
基本名称bultin可以帮助解决此问题,因为您专门将/分为以下部分:
user@host# var=/path/to/file.extension
user@host# basename ${var%%.*}
file
user@host#
它实际上并没有比两行变体快,但是使用内置功能只是一行。或者,使用zsh / ksh可以进行模式嵌套。:)
尽管这是一个非常古老的线程,但该设备非常适合直接或随机选择文件/目录进行处理(播放音乐,挑选要观看的电影或阅读书籍等)。
在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[...]}
因此,您有四个嵌套的扩展。
ARR=('foo' 'bar' 'bogus'); i=0; while /bin/true ; do echo ${ARR[$i]} ; i=(( (i + 1) % 3 )); done
它显然对代码没有用,但仅作为示例。