2
votes

Existe-t-il un moyen, dans bash, de rechercher une liste d'entiers pour des séquences consécutives et de supprimer tous les nombres sauf les derniers dans ces séquences?

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 commentaires

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".


3 Réponses :


0
votes

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]})


3 commentaires

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.



3
votes

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


0 commentaires

0
votes

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 .
  • Le préfixe 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.
  • Aucune vérification n'est effectuée pour s'assurer que les lignes d'entrée contiennent (uniquement) des nombres décimaux. Un vrai programme devrait faire de telles vérifications.
  • Comme aucune vérification n'est effectuée sur la validité de l'entrée, le code utilise 'printf' au lieu de 'echo' pour réduire les risques de confusion si l'entrée est mauvaise. Voir Pourquoi printf est-il meilleur que echo? .


0 commentaires