5
votes

Comment puis-je incrémenter un nombre à la fin d'une chaîne dans bash?

Fondamentalement, je dois créer une fonction où un argument est passé, et je dois mettre à jour le numéro, par exemple l'argument serait

version_2 et après la fonction, il le changerait en version_3

incrémente simplement de un.

en java, je créerais simplement une nouvelle chaîne, et saisirais la dernière mise à jour de caractère de un et l'ajouterais, mais je ne sais pas comment le faire dans bash.

updateVersion() {
  version=$1
}

le préfixe peut être n'importe quoi, par exemple il peut être dog12 ou dog_12 et a toujours un numéro à mettre à jour.

après la mise à jour, ce serait respectivement dog13 ou dog_13.


7 commentaires

Ce numéro est-il toujours après un _ ?


Êtes-vous sûr de votre solution Java? La version_19 ne devrait pas être mise à jour vers la version_110 , n'est-ce pas?


@CharlesDuffy Oui.


@choroba Oui, je le prendrais pour le convertir en un int et le faire ++.


@CharlesDuffy En fait, je ne pense pas, mais la version aura toujours un numéro dedans, pas d'autres numéros, comme version10 ou version_11 etc.


Est-il garanti que version sera le préfixe? (Vous avez eu au moins une réponse en supposant autant).


@CharlesDuffy Non, le préfixe peut être quelque chose comme il peut être dog_12 ou dog13 mais changerait respectivement en dog_13 et dog14, j'aurais dû le spécifier dans le message original.


4 Réponses :


4
votes
updateVersion()
{
    [[ $1 =~ ([^0-9]*)([0-9]+) ]] || { echo 'invalid input'; exit; }     
    echo "${BASH_REMATCH[1]}$(( ${BASH_REMATCH[2]} + 1 ))"
}

# Usage
updateVersion version_11         # output: version_12
updateVersion version11          # output: version12
updateVersion something_else123  # output: something_else124
updateVersion "with spaces 99"   # output: with spaces 100

# Putting it in a variable
v2="$(updateVersion version2)"
echo "$v2"                       # output: version3

1 commentaires

J'ai choisi celui-ci parce que c'est le plus simple. Vous étiez tous de très bonnes réponses et j'ai beaucoup appris merci!



2
votes
$ incrementTrailingNumber version_30
version_31
$ incrementTrailingNumber foo-2.15
foo-2.16
$ incrementTrailingNumber noNumberHereAtAll  # demonstrate noop case
noNumberHereAtAll

0 commentaires

2
votes

Utiliser l'expansion des paramètres:

#! /bin/bash
shopt -s extglob
for version in version_1 version_19 version_34.14 ; do
    echo $version
    v=${version##*[^0-9]}
    ((++v))
    echo ${version%%+([0-9])}$v
done

extglob est nécessaire pour la construction + ([0-9]) qui signifie "un ou plusieurs chiffres ".


0 commentaires

3
votes

En retard à la fête ici, mais il y a un problème avec la réponse acceptée. Cela fonctionne pour le cas de l'OP où il n'y a pas de nombres avant la fin, mais j'ai eu un exemple comme celui-ci:

1.0.143

Pour cela, l'expression rationnelle doit être un peu plus lâche. Voici comment je l'ai fait, en préservant les zéros non significatifs:

#!/usr/bin/env bash

updateVersion()
{
  [[ ${1} =~ ^(.*[^0-9])?([0-9]+)$ ]]  && \
    [[ ${#BASH_REMATCH[1]} -gt 0 ]] && \
      printf "%s%0${#BASH_REMATCH[2]}d" "${BASH_REMATCH[1]}" "$((10#${BASH_REMATCH[2]} + 1 ))" || \
      printf "%0${#BASH_REMATCH[2]}d" "$((10#${BASH_REMATCH[2]} + 1))" || \
    printf "${1}"
}

# Usage
updateVersion 09          # output 10
updateVersion 1.0.450     # output 1.0.451
updateVersion version_01  # output version_02
updateVersion version12   # output version13
updateVersion version19   # output version20

Notes:

  1. Il vous suffit de doubler le premier argument de printf .
  2. Remplacez $ {1} par le contenu de "" si vous souhaitez l'utiliser sur une ligne de commande, au lieu de dans une fonction.
  3. Vous pouvez changer le dernier printf en un écho de base si vous préférez. Si vous imprimez simplement vers stdout ou stderr , pensez à ajouter une nouvelle ligne ( \ n ) à la fin de chaque printf code>.
  4. Vous pouvez combiner le contenu de la fonction en une seule ligne, mais c'est plus difficile à lire. Il est préférable de le diviser en lignes avec \ à chaque if ( && ) et else ( || ), comme ci-dessus.

Ce que fait la fonction - ligne par ligne:

  • Tester la valeur transmise se termine par un nombre d'un ou plusieurs chiffres, éventuellement préfixé par au moins un non-nombre. Divisez en deux groupes en conséquence (l'indexation est basée sur 1).
  • Lorsque vous terminez par un nombre, vérifiez qu'il existe un préfixe non numérique (c.-à-d. longueur du groupe 1> 0).
  • Lorsqu'il n'y a pas de chiffres, affichez le groupe 1 (une chaîne) suivi du groupe 2 (un entier complété par des zéros pour correspondre à la taille de la chaîne d'origine). Le groupe 2 est converti en base 10 et incrémenté de 1. La conversion est importante - les zéros non significatifs sont interprétés comme octaux par défaut.
  • Lorsqu'il n'y a que des nombres, incrémentez comme ci-dessus mais imprimez simplement le groupe 2.
  • Si l'entrée est autre chose, renvoyez la chaîne fournie.


0 commentaires