17

I have the following script to launch a MySQL process:

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

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

What does 1:0:1 mean in this context?

migrated from serverfault.com Dec 17 '15 at 0:12

This question came from our site for system and network administrators.

  • 1
    I'd really like to know the answer, but I feel this is a bit of a too narrow question for SF. I'm voting to migrate it to the Unix site. – Massimo Dec 16 '15 at 23:17
17

It's a test for a - dashed argument option, apparently. It's a little strange, really. It uses a non-standard bash expansion in an attempt to extract the first and only the first character from $1. The 0 is the head character index and the 1 is string length. In a [ test like that it might also be:

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

Neither comparison is particularly suited to test though, as it interprets - dashed arguments as well - which is why I use the leading space there.

The best way to do this kind of thing - and the way it is usually done - is :

case $1 in -*) mysqld_safe "$@"; esac
  • 1
    Close; the number following the second colon in ${1:0:1} is a length, not an index. – chepner Dec 17 '15 at 4:04
  • In a bashism way with [[: [[ $1 == -* ]]. – Arthur2e5 Dec 17 '15 at 4:15
  • 2
    Personally I don't think those - will be a problem for test here.. POSIX gives definitions of the meanings by argument count. Since there is no such option that takes two arguments, it should be safe to write it in raw. – Arthur2e5 Dec 17 '15 at 4:19
  • @Arthur2e5 - you're right - they shouldn't be a problem - and very likely are not problematic at all. it's still a strange way to go at it - it just doesn't fit well. what does [[ : [[ do? – mikeserv Dec 17 '15 at 4:23
  • 1
    @mikeserv Well you should look at the webpage (if you are reading this from elsewhere).. My comment was like 'with START_CODE[[END_CODE: START_CODE[[ $1 == -*]]END_CODE'. The first [[ is just the syntax name, and the colon is just a punctuation. – Arthur2e5 Dec 17 '15 at 4:41
10

This is going to take a substring of $1 from the 0th to the 1st character. So you're going to get the first character and only the first character of the string.

From the bash 3.2 man page:

  ${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.
6

It is testing that the first character of the first argument $1 is a dash -.

The 1:0:1 are the values for the parameter expansion: ${parameter:offset:length}.

That means:

  • Name: the parameter named 1, i.e: $1
  • Start: from the first character 0 (numbered from 0).
  • Length: for 1 character.

In short: the first character of the first positional parameter $1.
That parameter expansion is available in ksh, bash, zsh (at least).


If you want to change the test line:

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

Bash options

Other safer bash solutions may be:

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

Safer because this have no issues with quoting (no split is executed inside [[)

POSIXly options.

For older, less capable shells, could be changed to:

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

Only the case command is more resistant to wrong quoting.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.