Signification de [“$ {1: 0: 1}” = '-']

18

J'ai le script suivant pour lancer un processus MySQL:

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

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

Que signifie 1: 0: 1 dans ce contexte?

user3521621
la source
1
J'aimerais vraiment connaître la réponse, mais je pense que c'est une question un peu trop étroite pour SF. Je vote pour le migrer vers le site Unix.
Massimo

Réponses:

19

C'est un test pour une -option d'argument pointillé, apparemment. C'est un peu étrange, vraiment. Il utilise une bashextension non standard dans le but d'extraire le premier et uniquement le premier caractère de $1. L' 0est l'index de caractère de tête et la 1est longueur de la chaîne. Dans un [ testpareil ça pourrait aussi être:

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

Aucune des deux comparaisons n'est particulièrement adaptée à testcela, car elle interprète également les -arguments en pointillés - c'est pourquoi j'y utilise l'espace de tête.

La meilleure façon de faire ce genre de chose - et la façon dont cela se fait habituellement - est:

case $1 in -*) mysqld_safe "$@"; esac
mikeserv
la source
1
Fermer; le nombre suivant le deuxième deux-points ${1:0:1}est une longueur, pas un index.
chepner
D'une certaine façon de bash avec [[: [[ $1 == -* ]].
Arthur2e5
2
Personnellement, je ne pense pas que ce -sera un problème pour testici. POSIX donne des définitions des significations par nombre d'arguments. Puisqu'il n'y a pas une telle option qui prend deux arguments, il devrait être sûr de l'écrire en raw.
Arthur2e5
@ Arthur2e5 - vous avez raison - cela ne devrait pas poser de problème - et très probablement pas du tout problématique. c'est toujours une façon étrange de s'y prendre - ça ne va tout simplement pas bien. qu'est-ce que ça [[ : [[fait?
mikeserv
1
@mikeserv Eh bien, vous devriez regarder la page Web (si vous lisez ceci ailleurs). Mon commentaire était comme "avec START_CODE [[END_CODE: START_CODE [[$ 1 == - *]] END_CODE". Le premier [[n'est que le nom de la syntaxe et les deux-points ne sont qu'une ponctuation.
Arthur2e5
11

Cela va prendre une sous-chaîne du $10ème au 1er caractère. Vous allez donc obtenir le premier caractère et uniquement le premier caractère de la chaîne.

Depuis la bashpage de manuel 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.
poussins
la source
6

Il teste que le premier caractère du premier argument $1est un tiret -.

Le 1: 0: 1 sont les valeurs de l'expansion de paramètres: ${parameter:offset:length}.

Cela signifie:

  • Nom: le paramètre nommé 1, c'est-à-dire:$1
  • Début: à partir du premier caractère 0(numéroté de 0).
  • Longueur: pour 1 caractère.

En bref: le premier caractère du premier paramètre positionnel $1.
Cette extension de paramètre est disponible en ksh, bash, zsh (au moins).


Si vous souhaitez modifier la ligne de test:

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

Options de bash

D'autres solutions de bash plus sûres peuvent être:

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

Plus sûr car cela n'a aucun problème avec les devis (aucun fractionnement n'est exécuté à l'intérieur [[)

Options POSIXly.

Pour les obus plus anciens et moins performants, pourrait être changé en:

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

Seule la commande case résiste mieux aux citations erronées.


la source