2009-05-27 15 views
42

は私が持っていることはこれです:

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

が、これは1行、すなわち単一の式に(またはしない)入れ子にすることはできますか?

スクリプト名のパスと拡張子を削除して、ベース名のみを残そうとしています。上の2行は正常に動作します。私の「C」の性質は、これらをさらに難読化するために単に私を運転しています。

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

答えて

35

巣によるならば、あなたはこのような何かを意味する:

+2

+1ベース名の参照。 –

+0

インデックスを使用している場合は、正しいことがありますか?たとえば、 'ARR =( 'foo' 'bar' 'bogus'); i = 0; while/bin/true; echo $ {ARR [$ i]};を実行します。 i =(((i + 1)%3));コードとしては無意味ですが、例として動作します。 –

+2

実際、この*は、少なくとも 'bash'と' ksh'でサポートされることがあります。これはうまくいきます: 'x = yyy; y = xxxyyy;エコー$ {y%$ {x}} '。重要なのは、ネストされた展開が演算子の1つの引数だということです。私はそれが本当にうまく文書化されていることを見ていない。 – twalberg

6

このネスティングはbashで可能であるようには見えないが、それはzshの中で働く

#!/bin/bash 

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

echo ${${HELLO}WORLD}

次にいや、することができます入れ子式は${var}です。 bashシンタックスエキスパンダーはそれを理解しません。

しかし、私があなたの問題を正しく理解していれば、basenameコマンドを使って見ることができます - 指定されたファイル名からパスを削除し、拡張子が与えられていればそれも削除されます。たとえば、basename /some/path/to/script.sh .shを実行すると、scriptが返されます。

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

それは本当に速い2つのラインバリアントよりはありませんが、それは内蔵使用してちょうど1行です:

1

あなたは、具体的に分割しているので、ベース名bultinは一部に/、これを助けることができます機能的にはあるいは、パターンネストを行うことができるzsh/kshを使用してください。 :)

+0

ご迷惑をおかけします。やってみなよ。私が逃したとティムが言ったように:) var = $(ベース名$ {var %%。*}) – dannysauer

+0

か、bash特有のベース名拡張子の削除を使用してください:D – dannysauer

1

私はこれが古代の糸だと知っていますが、ここに私の2セントです。

ここで必要な機能を可能にする(確か場しのぎ)bashの関数の:

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

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

ここ短いテストスクリプトです

30

間接拡張をサポートするBash:

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

これは、探しているネストをサポートする必要があります。

+0

こんにちは!シェルの意味ですか?それはここでfoobarの値に置き換えられることを意味しますか? – Mike

+1

@Mike http://wiki.bash-hackers.org/syntax/pe#indirection – Sparhawk

+0

素晴らしい例です。この場合、インダイレクション・パラメータ拡張が利用できない場合はどうなりますか? –

5

実際には、2つのステップを使用して、bashで入れ子になった変数を作成することは可能です。

ここには、user1956358が提案したアイデアを使用して、Timの投稿に基づくテストスクリプトがあります。

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

シェルパラメータ展開」を探して、その後、コマンドラインから「情報bashの」を実行することによって説明さ端正なトリックがたくさんあります。私は今日自分のことをいくつか読んでいましたが、私の日の約20分を失ってしまいましたが、スクリプトはもっと良くなるでしょう...

更新:私はあなたの最初の質問ごとにこの代替案を提案します。

progname=${0##*/} 

それは${${a}}よう

bash 
1

式は動作しません返します。これを回避するには、evalを使用することができます動機は「(私は流線を言う)Pythonのの精神の配列処理を「難読化」することである場合

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

出力は

value

0

です操作を順番に実行するヘルパー関数を作成します。

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

結果を素敵な1ライナーで使用できます。

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

配列を使用して呼び出すときは、http://stackoverflow.com/q/16461656を忘れないでください。 – nobar

8

古いスレッドおそらく答えは間接の使用である:{!PARAMETER}:

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

次のオプションがのために働いている$などについては

は、次の行を考えるには、私:

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

出力は次のとおりです。

par2 
+0

これは最高の答えです –

-1

のevalはあなたが欠けているものを行うことができます:

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

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

出力:Hello, world

1

OPの元の質問に1つのラインソリューション、ファイルとスクリプトのベース名があります拡張子は取り除か:

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

ここでベース名用のチートを使用して、別のですが、し:

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

他の答えが離れOPの元の質問からさまよい、それはちょうど${!var}と式の結果を拡張することが可能ですかどうかに焦点を当てたが、varが明示的に変数名と一致する必要があります制限に出くわしてきました。あなたがセミコロンで式を連鎖すると、1ライナーの答えが得られなくなることは何もありません。

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 
+0

間接指示の説明をありがとう!実際には、既存の変数名を参照するためにしか使用できないことは残念です。もちろん、オンライナーを作ることはできますが、一時変数の割り当てを伴うことは、私が避けようとしていたものです。 –

+0

@ steven-lu私の 'deref()'関数はどうですか?それが宣言されていれば、一時変数なしでonelinerを使用できますか? –

+0

これは、一時変数の使用よりも保守に2〜3倍多く混乱しているような妥当な対策によって、Cのプリプロセッサの濫用を思い起こさせる –

関連する問題