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?


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

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.

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.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.