Je recherche une méthode pour imprimer le plus long nombre dans une chaîne.
Par exemple: si j'ai la chaîne
212334123434test233
comment imprimer
212334123434
?
Remarque: je recherche la séquence de nombres continue la plus longue, pas la valeur numériquement supérieure.
Edit: Merci pour les réponses, tout le monde. La réponse à cette question a été assez écrasante. J'ai marqué le message de @ HaukeLaging comme réponse acceptée car cela convenait très bien à mon cas spécifique, mais je voudrais souligner que toutes les réponses sont également valables. C'est toujours bien d'avoir plusieurs options différentes pour résoudre un problème.
text-processing
sed
awk
Glutanimate
la source
la source
Réponses:
la source
Je crois que vous pouvez le faire avec juste
grep
,sort
ettail
aussi bien. Voici quelques exemples de chaînes.Où
<str>
est notre chaîne en question.Exemple
Maintenant, si je les exécute
grep ...
à tour de rôle via ma commande.Cette approche fonctionne en sélectionnant toutes les sous-chaînes qui sont des séquences de chiffres. Nous trions ensuite cette sortie numériquement,
sort -n
puis récupérons la dernière valeur de la liste à l'aide detail -1
. Ce sera la sous-chaîne la plus longue.Vous pouvez voir comment cela fonctionne en retirant
tail -1
et en réexécutant l'un des exemples:Chaînes commençant par des zéros
L'approche ci-dessus fonctionne pour toutes les situations que je pourrais concevoir sauf une. @terdon a mentionné dans le chat ce scénario qui déjoue l'approche ci-dessus.
Donc, pour y faire face, vous devrez légèrement changer de tactique. Le noyau de l'approche ci-dessus peut encore être exploité, mais nous devons également injecter le nombre de caractères dans les résultats. Cela donne à tri la possibilité de trier les résultats par nombre de caractères dans les chaînes et leurs valeurs.
Résultats:
Vous pouvez condenser cela un peu en utilisant la capacité de Bash à déterminer la longueur d'une variable à l'aide
${#var}
.Utilisation de `grep -P
J'ai choisi d'utiliser
grep -P ...
ci-dessus parce que moi, étant un développeur Perl, j'aime la syntaxe de classe de dire tous les chiffres comme ceci:,\d+
au lieu de[[:digit:]]\+
ou[0-9]\+
. Mais pour ce problème particulier, il n'est pas vraiment nécessaire. Vous pouvez tout aussi facilement échanger celuigrep
que j'ai utilisé comme ceci:Par exemple:
la source
${#i}
pour obtenir la longueur de la chaîne peut vous éviter d'appelerwc
, si vous voulez aller spécifique à bashgrep -o "[0-9]\+"
place degrep -oP "\d+"
Une solution en
perl
:Les références
la source
En utilisant python avec la chaîne passée sur la ligne de commande et en supposant que vous voulez la première séquence de longueur maximale:
la source
python -c "import re,sys; print max(re.split(r'\D+', sys.argv[1]), key=len)"
Voici une autre approche Perl qui peut traiter aussi bien les décimales que les entiers:
Notez qu'aucune des réponses publiées jusqu'à présent ne traitera des décimales et puisque vous spécifiez que vous voulez le nombre le plus long et non le plus grand numériquement, je suppose que vous avez réellement besoin de décimales.
Explication
perl -lne
: Le-n
moyen "lit l'entrée ligne par ligne, et exécute le script donné par-e
dessus". Le-l
ajoute une nouvelle ligne à chaqueprint
appel (et d'autres choses non pertinentes ici).while(/([\d.]+)/g)
: parcourez tous les nombres (\d
signifie[0-9]
que[\d.]
les chiffres correspondront ainsi.
. Si vous souhaitez également rechercher des nombres négatifs, ajoutez-
. Les parenthèses capturent la chaîne correspondante telle$1
qu'elle est utilisée à l'étape suivante.$max=$1 if length($1) > length($max)
: Si la longueur de la correspondance actuelle est supérieure à la plus longue jusqu'à présent ($max
), enregistrez la correspondance sous$max
.print $max
: affiche la plus longue chaîne de nombres trouvée. Cela sera exécuté une fois la boucle while terminée, donc une fois tous les nombres trouvés.la source
\D(\d+(?:\.\d+)?)\D
place.\D
ancres ....
comme dans les adresses IP.Donné
puis en bash
Une solution bash peut-être plus pure utilisant un tableau construit en remplaçant les caractères non numériques de la chaîne par des espaces, à la place de grep
la source
S'appuyant sur la réponse de @mikeserv, voici encore une autre alternative. Il extrait les nombres (selon la méthode de mikeserv), puis les trie par ordre numérique et prend le dernier. À l'exception des zéros non significatifs, cela vous donnera le plus grand nombre (sans tenir compte du signe):
la source
set -- $(echo $str | tr ... ) ; b=${#1} ; for d ; do [ ${#d} -gt $b ] && b=${#d} n=$d ; done ; echo $n
tr
toute façon, je ne vous en voudrai pas si vous intégriez ce qui précède. C'est probablementsort
plus rapide, mais, là encore, il attend la fin du flux de la même manière que le$(subshell)
. Je ne sais pas. En tout cas, la vôtre est déjà une excellente réponse, mais si vous avez envie d'ajouter la boucle de shell ci-dessus, n'hésitez pas. Et au fait - il est possible que vous puissiez vous passersort
complètement d'un peu de manipulation créative dewc -L
ettee
dans le flux ... J'en ai fini avec cette question - je suis gêné.tr
du sous-shell et vous en débarrasserprintf
. Faites-le'0-9' '\n'
.bash et tri GNU
la source
Utilisez des caractères non numériques pour fractionner la chaîne et recherchez la séquence la plus longue ou la plus grande valeur numérique (pour les nombres de longueur égale) avec un opérateur ternaire.
Vous pouvez également définir le séparateur d'enregistrement awk (
RS
) comme n'importe quelle chaîne de caractères non numérique:la source
RS = '[^0-9]+'
et utiliser la boucle inhérente d'Awk?echo "212334123434test233" | awk -v RS='[^0-9]+' 'length(longest) < length($0) {longest = $0};END{print longest}' 212334123434
RS
variable, je dois admettre que c'est la première fois que je la vois. Vous avez plus de conseils à offrirawk
que moi hahaha!