2009-05-27 71 views
42

我有是這樣的:

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

可以這樣嵌套(或不)成一條線,即,單一的表達?

我試圖剝離腳本名稱的路徑和擴展名,以便只剩下基本名稱。以上兩行工作正常。我'C'的本性讓我更加混淆了這些。

回答

35

如果窩,你的意思是這樣的:

#!/bin/bash 

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

echo ${${HELLO}WORLD}

然後沒有,你可以嵌套0​​表達式。 bash語法擴展器不會理解它。

但是,如果我理解你的問題是正確的,你可以看看使用basename命令 - 它從給定文件名剝離路徑,並且如果給定擴展名,也將剝離它。例如,運行basename /some/path/to/script.sh .sh將返回script

+2

+1爲基準名稱引用。 – 2009-05-27 19:09:27

+0

如果你使用的是索引,他們可以,對嗎?例如,'ARR =('foo''bar''bogus'); I = 0;而/ bin/true;做echo $ {ARR [$ i]}; i =(((i + 1)%3));完成「,這顯然是無用的代碼,但作爲一個例子。 – 2013-01-07 21:58:16

+2

實際上,這個*在某些情況下被支持,至少在`bash`和`ksh`中被支持。這工作:`x = yyy; Y = XXXYYY; echo $ {y%$ {x}}`。我認爲重要的一點是嵌套擴展是其中一個操作員的論點。儘管如此,我還沒有看到它記錄得很好。 – twalberg 2013-01-07 22:07:29

6

這種嵌套不會出現在bash是可能的,但它的zsh工作:

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

基名bultin可以解決這個問題,因爲你明確劃分開/在一個部分:

[email protected]# var=/path/to/file.extension 
[email protected]# basename ${var%%.*} 
file 
[email protected]# 

這不是真的比二本上線變種速度快,但它是一個使用內置只有一行功能。或者,使用zsh/ksh可以完成模式嵌套的事情。 :)

+0

抱歉關於格式。去嘗試一下。 :) var = $(basename $ {var %%。*}) – dannysauer 2009-05-27 19:45:52

1

我知道這是一個古老的線程,但這裏是我的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 
30

Bash支持間接擴展:

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

這應該支持您正在尋找的嵌套。

5

實際上,可以使用兩個步驟在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! 

有很多由在命令行中運行「信息慶典」,然後「殼牌參數擴展」搜索解釋巧妙的技巧的。我今天一直在讀一些自己,只是失去了我一天中的大約20分鐘,但我的腳本將會變得更好......

更新:在更多閱讀之後,我建議您根據您的第一個問題提供此替代方案。

progname=${0##*/} 

它返回

bash 
1

表達式像${${a}}不起作用。要解決它,你可以使用eval

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

輸出是

value

0

如果動機是「模糊」(我會說流)陣列處理在Python的精神「理解「,創建一個幫助函數,按順序執行操作。

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

您可以使用一個很好的單行結果。

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

一個古老的線程,但也許答案是採用間接:{!參數} $

對於例如,請考慮下面幾行:

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

以下選項供工作我:

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

輸出是:

par2 
-1

EVAL將讓你做你想要什麼:

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

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

輸出:Hello, world

1

有一個1行地解決了OP的原題,腳本與文件的基本名擴展剝離:

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

這裏的另一種,但是,使用欺騙的基本名稱:

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

其他答案已經逛到從OP的原題,距離集中在是否可能只是擴大與${!var}表達式的結果,而是跨var必須明確匹配變量名的限制來了。話雖如此,但如果將表達式與分號鏈接在一起,沒有任何東西可以阻止您獲得單線答案。

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

如果你想使這個看起來像一個單獨的語句,你可以窩在其一個子shell,即

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