23

人為的な例...与えられた

FOO="/foo/bar/baz"

これは機能します(bashで)

BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1}       # result is BAZ="b"

これはしません

BAZ=${$(basename $FOO):0:1} # result is bad substitution

私の質問は、この [サブシェル置換] が正しく評価されない原因となるルールはどれですか? また、これを 1 ホップで行う正しい方法は何ですか?

4

6 に答える 6

14

まず、これを言うときは次のことに注意してください。

BAR=$(basename $FOO) # result is BAR="baz"
BAZ=${BAR:0:1}       # result is BAZ="b"

for コンストラクトの最初のビットは、最初の文字を取得するBAZではBARありません。そのため、bash が変数名に任意の文字を含めることを許可したとしても、2 番目の式の結果はあなたが望むものにはなりません。

ただし、これを妨げているルールについては、bash の man ページから引用させてください。

DEFINITIONS
       The following definitions are used throughout the rest  of  this  docu‐
       ment.
       blank  A space or tab.
       word   A  sequence  of  characters  considered  as a single unit by the
              shell.  Also known as a token.
       name   A word consisting only of  alphanumeric  characters  and  under‐
              scores,  and beginning with an alphabetic character or an under‐
              score.  Also referred to as an identifier.

それから少し後:

PARAMETERS
       A parameter is an entity that stores values.  It can be a name, a  num‐
       ber, or one of the special characters listed below under Special Param‐
       eters.  A variable is a parameter denoted by a name.  A variable has  a
       value  and  zero or more attributes.  Attributes are assigned using the
       declare builtin command (see declare below in SHELL BUILTIN COMMANDS).

そして後で、あなたが求めている構文を定義するとき:

   ${parameter:offset:length}
          Substring Expansion.  Expands to  up  to  length  characters  of
          parameter  starting  at  the  character specified by offset.

そのため、マンページに明確に示されている規則では、${foo:x:y}構造体は最初の部分としてパラメーターを持たなければならず、パラメーターは名前、数値、またはいくつかの特殊なパラメーター文字の 1 つだけにすることができます。$(basename $FOO)パラメーターに許可されている可能性の 1 つではありません。

1 つの割り当てでこれを行う方法については、他の応答で述べたように、他のコマンドへのパイプを使用します。

于 2011-05-06T22:39:40.040 に答える
7

変更された形式のパラメータ置換などは${parameter#word}、パラメータのみを変更でき、任意の単語は変更できません。

この場合、の出力をbasename次のようにddコマンドにパイプすることができます。

BAR=$(basename -- "$FOO" | dd bs=1 count=1 2>/dev/null)

(より多くのカウントが必要な場合は、増やしてください。そうcountしないとbs、要求されたバイト数よりも少なくなる可能性があります。)

一般的なケースでは、1つの割り当てでこのようなことを行う方法はありません。

于 2011-05-06T22:25:00.947 に答える
6

${BAR:0:1}は可変展開であるため失敗します。Bashは${、値ではなく、の後に変数名が表示されることを期待しています。

単一の式でそれを行う方法を私は知りません。

于 2011-05-06T22:26:20.783 に答える
4

他の人が言ったように、 ${} の最初のパラメーターは変数名である必要があります。ただし、別のサブシェルを使用して、やろうとしていることを近似することができます。

それ以外の:

BAZ=${$(basename $FOO):0:1} # result is bad substitution

使用する:

BAZ=$(_TMP=$(basename $FOO); echo ${_TMP:0:1}) # this works
于 2016-03-06T18:14:09.297 に答える
0

${string:0:1},string は変数名でなければなりません

例えば:

FOO="/foo/bar/baz"

baz="フー"

BAZ=eval echo '${'"$(basename $FOO)"':0:1}'

エコー $BAZ

結果は「f」

于 2014-02-13T07:08:29.877 に答える