Significado de ["$ {1: 0: 1}" = '-']

18

Eu tenho o seguinte script para iniciar um processo MySQL:

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

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

O que 1: 0: 1 significa neste contexto?

user3521621
fonte
11
Eu realmente gostaria de saber a resposta, mas acho que essa é uma pergunta um pouco restrita para SF. Estou votando para migrá-lo para o site Unix.
Massimo

Respostas:

19

É um teste para uma -opção de argumento tracejado, aparentemente. É um pouco estranho, realmente. Ele usa uma bashexpansão não padrão na tentativa de extrair o primeiro e somente o primeiro caractere $1. O 0é o índice de caracteres principais e o 1comprimento da sequência. De uma [ testforma que também pode ser:

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

Nenhuma comparação é particularmente adequada test, pois interpreta -argumentos pontilhados - e é por isso que eu uso o espaço principal lá.

A melhor maneira de fazer esse tipo de coisa - e da maneira como geralmente é feita - é:

case $1 in -*) mysqld_safe "$@"; esac
mikeserv
fonte
11
Fechar; o número após o segundo cólon ${1:0:1}é um comprimento, não um índice.
chepner
De certa forma Bashismo com [[: [[ $1 == -* ]].
Arthur2e5
2
Pessoalmente, não acho que -isso será um problema para testaqui. O POSIX fornece definições dos significados por contagem de argumentos. Como não existe essa opção que requer dois argumentos, deve ser seguro escrevê-la em bruto.
Arthur2e5
@ Arthur2e5 - você está certo - eles não devem ser um problema - e muito provavelmente não são problemáticos. ainda é um caminho estranho a seguir - simplesmente não se encaixa bem. o que [[ : [[faz?
mikeserv
11
@mikeserv Bem, você deve olhar a página da Web (se estiver lendo isso de outro lugar) .. Meu comentário foi como 'com START_CODE [[END_CODE: START_CODE [[$ 1 == - *]] END_CODE'. O primeiro [[é apenas o nome da sintaxe, e os dois pontos são apenas uma pontuação.
Arthur2e5
11

Isso vai levar uma substring do $10º ao 1º caractere. Então você terá o primeiro caractere e apenas o primeiro caractere da string.

Na bashpágina do manual 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.
filhotes
fonte
6

Está testando que o primeiro caractere do primeiro argumento $1é um traço -.

O 1: 0: 1 são os valores para a expansão de parâmetros: ${parameter:offset:length}.

Que significa:

  • Nome: o parâmetro nomeado 1, ou seja:$1
  • Início: do primeiro caractere 0(numerado de 0).
  • Comprimento: para 1 caractere.

Em resumo: o primeiro caractere do primeiro parâmetro posicional $1.
Essa expansão de parâmetro está disponível em ksh, bash, zsh (pelo menos).


Se você deseja alterar a linha de teste:

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

Opções do Bash

Outras soluções mais seguras do bash podem ser:

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

Mais seguro, pois não há problemas com a citação (nenhuma divisão é executada dentro [[)

Opções POSIXly.

Para conchas mais antigas e menos capazes, poderia ser alterado para:

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

Somente o comando case é mais resistente a aspas erradas.


fonte