Значение [«$ {1: 0: 1}» = '-']

18

У меня есть следующий скрипт для запуска процесса MySQL:

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

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

Что означает 1: 0: 1 в этом контексте?

user3521621
источник
1
Мне бы очень хотелось узнать ответ, но я чувствую, что это слишком узкий вопрос для SF. Я голосую за его перенос на сайт Unix.
Массимо

Ответы:

19

Это тест для -опции пунктирного аргумента, по-видимому. Это немного странно, правда. Он использует нестандартное bashрасширение в попытке извлечь первый и только первый символ из $1. Индекс 0заголовка и 1длина строки. В , [ testкак , что он также может быть:

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

Однако ни одно из этих сравнений не подходит test, поскольку оно также интерпретирует -пунктирные аргументы - вот почему я использую пробел там.

Лучший способ сделать это - и как это обычно делается - это:

case $1 in -*) mysqld_safe "$@"; esac
mikeserv
источник
1
Близко; число после второго двоеточия в ${1:0:1}является длиной, а не индексом.
chepner
В bashism образом с [[: [[ $1 == -* ]].
Arthur2e5
2
Лично я не думаю, что это -будет проблемой testздесь. POSIX дает определения значений по количеству аргументов. Поскольку такой опции, которая принимает два аргумента, не существует, записывать ее в формате raw безопасно.
Arthur2e5
@ Arthur2e5 - вы правы - они не должны быть проблемой - и, скорее всего, не являются проблемой вообще. это все еще странный способ пойти на это - это просто не подходит. что делает [[ : [[?
mikeserv
1
@mikeserv Ну, вы должны посмотреть на веб-страницу (если вы читаете это откуда-то еще) .. Мой комментарий был похож на 'with START_CODE [[END_CODE: START_CODE [[$ 1 == - *]] END_CODE'. Первый [[- это просто имя синтаксиса, а двоеточие - просто пунктуация.
Arthur2e5
11

Это займет подстроку $1от 0-го до 1-го символа. Таким образом, вы получите первый символ и только первый символ строки.

Из bashсправочной страницы 3.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.
птенцы
источник
6

Он проверяет, что первый символ первого аргумента $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 более устойчива к неправильному цитированию.


источник