J’ai vraiment du mal à écrire un script shell Bourne. Fondamentalement, j’ai trois formats d’entrée pour une variable appelée “ref” que j’essaie de détecter:
Par exemple,
Si ref = “refs / head / master”, définissez TAG = “master”
Si ref = “refs / tags / 0.2.4”, définissez TAG = “0.2.4”
Pour tout le rest, définissez TAG = “”
Maintenant, j’ai écrit quelque chose dans shell bash, mais j’ai vraiment du mal à le convertir en Bourne (#! / Bin / sh):
#!/bin/bash # #This works! # TAG="" re='^refs/head/.*' #regex: begins with refs/head/, ends with anything re2='^refs/tags/.*' #regex: begins with refs/tags/, ends with anything if [[ $ref =~ $re ]]; then #do nothing - OK true #NOP else #check if it's a tag update if [[ $ref =~ $re2 ]]; then TAG=${$ref##*/} #looks worse that it is: http://stackoverflow.com/questions/3162385/how-to-split-a-ssortingng-in-shell-and-get-the-last-field fi exit 0 fi echo $TAG
Il m’a fallu des années pour: a) écrire ce programme et b) découvrir pourquoi mon programme devenait fou – il s’est avéré que j’avais besoin de #! / Bin / sh et non #! / Bin / bash
Comment puis-je convertir cela en sh? Peut-être que quelqu’un d’autre a une solution plus élégante à ma gymnastique regex?
Mettre à jour:
Merci pour les réponses sofar (surtout @gboffi). Je pense que je suis presque là.
Tout ce dont j’ai besoin maintenant, c’est de savoir si $ TAG provient de “refs / head /”, “refs / tags /” ou ni l’un ni l’autre. J’ai essayé de modifier certaines des réponses, mais j’ai vraiment du mal avec sh. Je dois partir et en apprendre plus sur sh à partir des premiers principes au lieu d’essayer de le pirater.
Mise à jour 2:
Donc, après une nuit de sumil, j’ai compris en 20 minutes environ. Voici ma solution:
#!/bin/sh ref="refs/asdf/master" TAG="" TAG="${ref#refs/heads/}" if [ "$ref" != "${ref#refs/heads/}" ]; then echo "heads" echo $TAG else TAG="${ref#refs/tags/}" if [ "$ref" != "${ref#refs/tags/}" ]; then echo "heads" echo $TAG else TAG="" fi fi echo "--->$TAG"
Je suis sûr qu’il existe une solution beaucoup plus élégante. mais je n’ai tout simplement pas le temps!
Vous pouvez utiliser rev-parse
pour cela, voici quelques exemples provenant de l’un de mes référentiels. Notez que le dernier ne produit aucune sortie, comme vous le souhaitez.
$ git rev-parse --abbrev-ref refs / chefs / maitre maîsortingser $ git rev-parse --abbrev-ref refs / tags / 5 5 $ git rev-parse --abbrev-ref @ ^
Ici c’est une fonction, définie en dash
(la version Linux de sh
)
% dash $ tag() { > TAG="" > [ "$1" != "${1#refs/head/}" ] && TAG="${1#refs/head/}" > [ "$1" != "${1#refs/tags/}" ] && TAG="${1#refs/tags/}" > echo "$TAG" >} $ tag poldo $ tag refs/head/poldo poldo $ tag refs/tags/pippo pippo $ tag to093u0refs/head/poldo $exit %
Le moyen le plus idiomatique de gérer cela est d’utiliser une déclaration de cas et une correspondance de modèle:
#!/bin/sh case $ref in refs/head/*) true ;; # original behavior: no output, success refs/tags/*) printf '%s\n' "${ref##*/}" ;; # original behavior: emit output *) false # exit with an error # original code didn't specify behavior esac
La raison pour laquelle je quitte avec une erreur dans le cas où ni refs/head/*
ni refs/tags/*
correspond est que si vous voulez quitter avec succès dans ce cas, vous pouvez omettre complètement le test refs/head/*
.
Après avoir lu votre description de la fonction souhaitée, il semble que cela se résume à ceci:
ainsi, en supposant que votre entrée est dans la variable REF,
TAG="" echo $REF | egrep -q 'refs/head|refs/master' if [ $? -eq 0 ] then TAG=`echo $REF | sed "s/.*\///"` fi
doit le faire.
(Note latérale pour les têtes de shell: basename est-il une meilleure solution que sed dans ce cas particulier?)