["${1:0:1}" = '-' ] 的含义

use*_*621 21 linux shell bash

我有以下脚本来启动 MySQL 进程:

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

if [ "$1" = 'mysqld_safe' ]; then
    DATADIR="/var/lib/mysql"
...
Run Code Online (Sandbox Code Playgroud)

在这种情况下,1:0:1 是什么意思?

mik*_*erv 21

-显然,这是对虚线参数选项的测试。这有点奇怪,真的。它使用非标准bash扩展尝试从$1. 的0是头部字符索引和1是字符串长度。在[ test类似的情况下,它也可能是:

[ " -${1#?}" = " $1" ]
Run Code Online (Sandbox Code Playgroud)

test但是,这两种比较都不是特别适合,因为它也解释了-虚线参数 - 这就是我在那里使用前导空格的原因。

做这种事情的最好方法——通常也是这样做的——是:

case $1 in -*) mysqld_safe "$@"; esac
Run Code Online (Sandbox Code Playgroud)

  • 我个人认为那些 `-` 不会成为这里 `test` 的问题.. [POSIX](http://pubs.opengroup.org/onlinepubs/9699919799/utilities/test.html) 给出了含义的定义按参数计数。由于没有这样的选项需要两个参数,所以用 raw 编写它应该是安全的。 (2认同)

chi*_*cks 11

这将采用$1从第 0 到第 1 个字符的子字符串。因此,您将获得字符串的第一个字符且仅是第一个字符。

从bash3.2 手册页:

  ${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.
Run Code Online (Sandbox Code Playgroud)


小智 8

它正在测试第一个参数的第一个字符$1是 dash -。

1:0:1 是参数扩展的值:${parameter:offset:length}。

这意味着:

  • Name:参数name 1,即:$1
  • 开始:从第一个字符0(从 0开始编号)。
  • 长度:1 个字符。

简而言之:第一个位置参数的第一个字符$1。
该参数扩展在 ksh、bash、zsh(至少)中可用。


如果要更改测试线:

[ "${1:0:1}" = "-" ]
Run Code Online (Sandbox Code Playgroud)

Bash 选项

其他更安全的 bash 解决方案可能是:

[[ $1 =~ ^- ]]
[[ $1 == -* ]]
Run Code Online (Sandbox Code Playgroud)

更安全,因为这没有引用问题(内部没有执行拆分[[)

POSIXly 选项。

对于较旧的、功能较弱的 shell,可以更改为:

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

只有 case 命令更能抵抗错误的引用。