Étant donné un nom de fichier dans le formulaire someletters_12345_moreleters.ext
, je veux extraire les 5 chiffres et les mettre dans une variable.
Donc, pour souligner le point, j'ai un nom de fichier avec x nombre de caractères puis une séquence de cinq chiffres entourée d'un seul trait de soulignement de chaque côté puis un autre ensemble de x nombre de caractères. Je veux prendre le nombre à 5 chiffres et le mettre dans une variable.
Je suis très intéressé par le nombre de façons différentes dont cela peut être accompli.
abc_12345_def_67890_ghi_def
est une entrée valide. Qu'est-ce que tu veux qu'il arrive? Supposons qu'il n'y ait qu'une seule séquence à 5 chiffres. Vous avez toujoursabc_def_12345_ghi_jkl
ou1234567_12345_1234567
ou12345d_12345_12345e
comme entrée valide en fonction de votre définition de l'entrée et la plupart des réponses ci-dessous ne traiteront pas cela._
délimiteur, entrée qui ne contient la chaîne cible qu'une seule fois, etc.). La meilleure réponse (la plus générique et la plus rapide) n'a, après 10 ans, que 7 votes positifs, tandis que d'autres réponses limitées en comptent des centaines. Me fait perdre confiance dans les développeurs 😞Réponses:
Utiliser la coupe :
Plus générique:
la source
echo
moins que vous ne sachiez avec certitude que les variables ne peuvent pas contenir des espaces blancs irréguliers ou des métacaractères shell. Voir plus stackoverflow.com/questions/10067266/…Si x est constant, l'expansion de paramètre suivante effectue l'extraction de la sous-chaîne:
où 12 est le décalage (basé sur zéro) et 5 est la longueur
Si les traits de soulignement autour des chiffres sont les seuls dans l'entrée, vous pouvez supprimer le préfixe et le suffixe (respectivement) en deux étapes:
S'il y a d'autres soulignements, c'est probablement possible de toute façon, bien que plus délicat. Si quelqu'un sait comment effectuer les deux extensions en une seule expression, j'aimerais aussi le savoir.
Les deux solutions présentées sont purement bash, sans apparition de processus, donc très rapide.
la source
bash: ${${a#*_}%_*}: bad substitution
sur mon GNU bash 4.2.45.sh
script, qui était probablement un tiret. À ce stade, je ne peux plus le faire fonctionner.:-
substitution «Utiliser les valeurs par défaut».${a: -12:5}
Donne donc les 5 caractères 12 caractères à partir de la fin, et${a: -12:-5}
les 7 caractères entre la fin 12 et la fin 5.Solution générique où le numéro peut être n'importe où dans le nom de fichier, en utilisant la première de ces séquences:
Une autre solution pour extraire exactement une partie d'une variable:
Si votre nom de fichier a toujours le format,
stuff_digits_...
vous pouvez utiliser awk:Encore une autre solution pour tout supprimer sauf les chiffres, utilisez
la source
essayez d'utiliser
cut -c startIndx-stopIndx
la source
startIndx-$((lastIndx-1))
start=5;stop=9; echo "the rain in spain" | cut -c $start-$(($stop-1))
git log --oneline | head -1 | cut -c 9-(end -1)
line=
divise en deux parties comme git log --oneline | head -1` && echo $ line | cut -c 9 - $ (($ {# line} -1)) `mais dans ce cas particulier, il serait préférable d'utiliser sed asgit log --oneline | head -1 | sed -e 's/^[a-z0-9]* //g'
Si quelqu'un veut des informations plus rigoureuses, vous pouvez également les rechercher dans man bash comme ceci
Résultat:
la source
${var: -4}
Voici comment je le ferais:
Explication:
Spécifique à Bash:
[[ ]]
indique une expression conditionnelle=~
indique que la condition est une expression régulière&&
enchaîne les commandes si la commande précédente a réussiExpressions régulières (RE):
_([[:digit:]]{5})_
_
sont des littéraux pour délimiter / ancrer les limites de correspondance pour la chaîne en correspondance()
créer un groupe de capture[[:digit:]]
est une classe de personnage, je pense qu'elle parle d'elle-même{5}
signifie exactement cinq du caractère précédent, la classe (comme dans cet exemple) ou le groupe doit correspondreEn anglais, vous pouvez penser qu'elle se comporte comme ceci: la
FN
chaîne est itérée caractère par caractère jusqu'à ce que nous voyions un_
point auquel le groupe de capture est ouvert et nous essayons de faire correspondre cinq chiffres. Si cette correspondance réussit à ce stade, le groupe de capture enregistre les cinq chiffres parcourus. Si le caractère suivant est un_
, la condition réussit, le groupe de capture est rendu disponible dansBASH_REMATCH
et l'NUM=
instruction suivante peut s'exécuter. Si une partie de la correspondance échoue, les détails enregistrés sont supprimés et le traitement caractère par caractère se poursuit après le_
. Par exemple, siFN
où_1 _12 _123 _1234 _12345_
, il y aurait quatre faux départs avant qu'il ne trouve une correspondance.la source
cut
). Il ne dépend pas non plus de l'exécution d'une commande externe.Je suis surpris que cette solution pure bash ne soit pas venue:
Vous voudrez probablement réinitialiser IFS à sa valeur avant ou
unset IFS
après!la source
IFS
IFS=_ read -r _ digs _ <<< "$a"; echo "$digs"
S'appuyant sur la réponse de Jor (qui ne fonctionne pas pour moi):
la source
cut
.Suivre les exigences
J'ai trouvé quelques
grep
moyens qui peuvent être utiles:ou mieux
Et puis avec la
-Po
syntaxe:Ou si vous voulez que cela corresponde exactement à 5 caractères:
Enfin, pour le stocker dans une variable il suffit d'utiliser la
var=$(command)
syntaxe.la source
Invocation as 'egrep' is deprecated; use 'grep -E' instead
. J'ai édité votre réponse.Si nous nous concentrons sur le concept de:
"Une série de (un ou plusieurs) chiffres"
Nous pourrions utiliser plusieurs outils externes pour extraire les chiffres.
Nous pourrions assez facilement effacer tous les autres personnages, sed ou tr:
Mais si $ name contient plusieurs séries de nombres, ce qui précède échouera:
Si "name = someletters_12345_moreleters_323_end.ext", alors:
Nous devons utiliser des expressions régulières (regex).
Pour sélectionner uniquement la première exécution (12345 et non 323) dans sed et perl:
Mais on pourrait aussi bien le faire directement en bash (1) :
Cela nous permet d'extraire la PREMIÈRE série de chiffres de n'importe quelle longueur
entourée de tout autre texte / caractère.
Remarque :
regex=[^0-9]*([0-9]{5,5}).*$;
ne correspondra qu'à exactement 5 séries de chiffres. :-)(1) : plus rapide que d'appeler un outil externe pour chaque texte court. Pas plus rapide que de faire tout le traitement dans sed ou awk pour les gros fichiers.
la source
Sans aucun sous-processus, vous pouvez:
Une très petite variante de ceci fonctionnera également dans ksh93.
la source
Voici une solution préfixe-suffixe (similaire aux solutions proposées par JB et Darron) qui correspond au premier bloc de chiffres et ne dépend pas des traits de soulignement environnants:
la source
J'adore
sed
la capacité de traiter avec des groupes d'expressions régulières:Une option un peu plus générale serait pas supposer que vous avez un trait de soulignement
_
marquant le début de votre séquence de chiffres, donc , par exemple , dépouillant tous les non-chiffres que vous obtenez avant votre séquence:s/[^0-9]\+\([0-9]\+\).*/\1/p
.Plus à ce sujet, au cas où vous ne seriez pas trop confiant avec les expressions régulières:
s
est pour _s_ubstitute[0-9]+
correspond à 1+ chiffres\1
liens vers le groupe n.1 de la sortie d'expression régulière (le groupe 0 est la correspondance complète, le groupe 1 est la correspondance entre parenthèses dans ce cas)p
le drapeau est pour _p_rintingToutes les échappées
\
sont là pour faire fonctionnersed
le traitement des expressions rationnelles.la source
Ma réponse aura plus de contrôle sur ce que vous voulez sortir de votre chaîne. Voici le code sur la façon d'extraire
12345
de votre chaîneCe sera plus efficace si vous voulez extraire quelque chose qui a des caractères comme
abc
ou des caractères spéciaux comme_
ou-
. Par exemple: si votre chaîne est comme ça et que vous voulez tout ce qui est aprèssomeletters_
et avant_moreleters.ext
:Avec mon code, vous pouvez mentionner exactement ce que vous voulez. Explication:
#*
Il supprimera la chaîne précédente, y compris la clé correspondante. Ici, la clé que nous avons mentionnée est_
%
Elle supprimera la chaîne suivante, y compris la clé correspondante. Ici, la clé que nous avons mentionnée est '_more *'Faites vous-même des expériences et vous trouverez cela intéressant.
la source
Étant donné que test.txt est un fichier contenant "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
la source
Ok, voici la substitution de paramètres pure avec une chaîne vide. La mise en garde est que j'ai défini des someletters et des moreletters comme étant uniquement des personnages. S'ils sont alphanumériques, cela ne fonctionnera pas tel quel.
la source
similaire à substr ('abcdefg', 2-1, 3) en php:
la source
Il y a aussi la commande bash builtin 'expr':
la source
expr
n'est pas une fonction intégrée.=~
opérateur soutenu par[[
.Un peu tard, mais je viens de rencontrer ce problème et j'ai trouvé ce qui suit:
Je l'ai utilisé pour obtenir une résolution en millisecondes sur un système embarqué qui n'a pas% N pour la date:
la source
Une solution bash:
Cela encombrera une variable appelée
x
. Le varx
peut être changé en var_
.la source
Fin Inklusive, similaire aux implémentations JS et Java. Supprimez +1 si vous ne le souhaitez pas.
Exemple:
Plus d'exemples d'appels:
Je vous en prie.
la source