web-dev-qa-db-ja.com

["$ {1:0:1}" = '-']の意味

MySQLプロセスを起動する次のスクリプトがあります。

if [ "${1:0:1}" = '-' ]; then
    set -- mysqld_safe "$@"
fi

if [ "$1" = 'mysqld_safe' ]; then
    DATADIR="/var/lib/mysql"
...

このコンテキストで1:0:1はどういう意味ですか?

19
user3521621

どうやら-の破線の引数オプションのテストです。ほんと少し奇妙です。 $1から最初の最初の文字のみを抽出するために、非標準のbash展開を使用します。 0は先頭文字のインデックスで、1は文字列の長さです。そのような[testでは、次のようになることもあります。

[ " -${1#?}" = " $1" ]

どちらの比較もtestには特に適していません。これは、-の破線の引数も解釈するためです。そのため、ここで先行スペースを使用しています。

この種のことを行うための最良の方法-通常の方法-は次のとおりです。

case $1 in -*) mysqld_safe "$@"; esac
20
mikeserv

これは、0番目から1番目の文字までの$1のサブストリングを取ります。したがって、文字列の最初の文字と最初の文字のみを取得します。

bash 3.2のmanページから:

  ${parameter:offset}
  ${parameter:offset:length}
          Substring  Expansion.   Expands  to  up to length characters of
          parameter starting at the character specified  by  offset.   If
          length is omitted, expands to the substring of parameter start-
          ing at the character specified by offset.   length  and  offset
          are  arithmetic  expressions (see ARITHMETIC EVALUATION below).
          length must evaluate to a number greater than or equal to zero.
          If  offset  evaluates  to a number less than zero, the value is
          used as an offset from the end of the value of  parameter.   If
          parameter  is  @,  the  result  is length positional parameters
          beginning at offset.  If parameter is an array name indexed  by
          @ or *, the result is the length members of the array beginning
          with ${parameter[offset]}.  A negative offset is taken relative
          to  one  greater than the maximum index of the specified array.
          Note that a negative offset must be separated from the colon by
          at  least  one space to avoid being confused with the :- expan-
          sion.  Substring indexing is zero-based unless  the  positional
          parameters are used, in which case the indexing starts at 1.
11
chicks

最初の引数$1の最初の文字がダッシュ-であることをテストしています。

1:0:1はパラメーター拡張の値です:${parameter:offset:length}

つまり:

  • 名前:1という名前のパラメーター、つまり$1
  • 開始:最初の文字0(0から始まる)。
  • 長さ:1文字分。

つまり、最初の位置パラメータ$1の最初の文字です。
そのパラメータ拡張は、ksh、bash、zsh(少なくとも)で利用できます。


テスト行を変更したい場合:

[ "${1:0:1}" = "-" ]

Bashオプション

他のより安全なbashソリューションは次のとおりです。

[[ $1 =~ ^- ]]
[[ $1 == -* ]]

これは引用の問題がないため安全です([[内で分割は実行されません)

POSIXlyオプション。

古い、能力の低いシェルの場合、次のように変更できます。

[ "$(echo $1 | cut -c 1)" = "-" ]
[ "${1%%"${1#?}"}"        = "-" ]
case $1 in  -*) set -- mysqld_safe "$@";; esac

Caseコマンドのみが、誤った引用に耐性があります。

6
user79743