Ma question est, étant donné une liste d'entiers, est-il possible dans bash de a) trouver toutes les séquences de nombres consécutifs, puis b) supprimer tous les nombres sauf les derniers dans ces séquences?
Par exemple, étant donné ceci list et en supposant que les nombres sont stockés, un par ligne, dans un fichier .txt,
10508 10861 10862 10906 10906 10909 10909 10950 10950 11179 11181 11182 11325 11325 11341 11341 11428 11428
y a-t-il un programme / ensemble de programmes qui produiraient une sortie
#!/bin/bash cat file.txt | numinterval >> interval.txt integer='' while read -u 3 interval do if [[ "$interval" -ne "1" ]] then echo "$integer" >> desequenced.txt else read -u 4 integer fi done 3< interval.txt 4< file.txt
et si oui, comment? Merci pour votre temps.
MODIFIER:
Voici ce que j'ai jusqu'ici:
003 005 007 012
L'idée centrale est de courir la liste triée d'entiers via numinterval, puis pour vérifier si la liste numinterval en contient. Si c'est le cas, passez à l'entier suivant. Sinon, imprimez l'entier correspondant dans un fichier.
001 002 003 005 007 010 011 012
Voici la sortie. De toute évidence, quelque chose ne va pas, car non seulement les consécutifs ne sont pas supprimés, mais il y a une énorme quantité d'espaces blancs après la fin de la liste.
Toute aide est appréciée.
3 Réponses :
J'ai écrit ce truc laid. Il vous suffit de comprendre comment créer votre arr
et comment joliment imprimer le résultat
.
arr=( 1 2 3 5 7 10 11 12 ) result=() k=0 for (( i=0; i<${#arr[@]} - 1 ; i++ )); do curArg=${arr[$i]} nextArg=${arr[$i+1]} if ((curArg != nextArg - 1 )); then result+=($curArg) fi done result+=(${arr[-1]})
Les indices de tableau sont déjà un contexte arithmétique, vous n'avez donc pas besoin de $ (())
dans []
. Vous n'en avez surtout pas besoin sur la dernière ligne puisque vous n'effectuez aucune arithmétique. Aussi, vous pouvez faire ((last = len - 1))
que je trouve plus propre. Votre if
serait mieux comme comparaison d'entiers: if ((curArg! = NextArg - 1))
. Vous semblez configurer le result
sous forme de tableau, mais vous l'ajoutez en tant que scalaire. Utilisez plutôt result + = ($ curArg)
. De plus, votre premier écho
semble être destiné à afficher une confirmation de la valeur du tableau. Vous devriez toujours citer des variables ...
... pour la sortie et vous devriez rarement utiliser *
pour un indice de tableau à moins que vous ne compreniez ce qu'il fait et que vous ayez réellement besoin de ce comportement. Utilisez plutôt echo "$ {arr [@]}"
. Encore mieux à des fins de test / confirmation: declare -p arr
qui montre la structure du tableau. Vous pouvez réduire vos attributions de last
et len
en n'attribuant que last
: ((last = $ {# arr [@]} - 1))
ou omettez son utilisation entièrement en utilisant for ((i = 0; i <$ {# arr [@]} - 1; i ++)); faire
(correction d'un point-virgule manquant) et result + = ($ {arr [-1]})
Sinon, bonne solution. À propos, Bash ne prend pas en charge les tableaux de tableaux.
Une façon, en utilisant awk:
$ awk 'NR > 1 && $0+0 != prev+1 { print prev } { prev = $0 } END { print prev }' test.txt 003 005 007 012
Essayez ce Shellcheck -clean pur code Bash:
#! /bin/bash -p prev= while read -r curr || [[ -n $curr ]] ; do [[ -n $prev ]] && (( 10#$curr != (10#$prev+1) )) && printf '%s\n' "$prev" prev=$curr done <file.txt [[ -n $prev ]] && printf '%s\n' "$prev"
|| [[-n $ curr]]
permet au code de fonctionner même si la dernière ligne du fichier d'entrée n'est pas terminée. Voir Lire un fichier ligne par ligne en attribuant la valeur à une variable . 10 #
dans 10 # $ curr
et 10 # $ prev
force le contenu de la variable à être traité comme des nombres décimaux. Sinon, 010
serait traité comme décimal 8 au lieu de décimal 10.
Oui, un tel programme peut être écrit. Est-ce votre seule question?
Erreur notée et corrigée.
Merci de clarifier. Cependant, cela est toujours hors sujet . Les questions sur le sujet fournissent un exemple reproductible minimal illustrant votre tentative de résolution du problème. Sinon, cela ressemble à une demande "donne-moi le code".