Forum Programmation.shell Opérations sur les lignes d'un fichier (soustraction de chiffres)

Posté par  . Licence CC By‑SA.
-1
17
oct.
2019

Bonjour,

Je souhaiterais soustraire la ligne i+1 à la ligne i d'un fichier pour i allant du début du fichier jusqu'à la fin en mettant 0 ou une ligne vide pour la première ligne.

Si on prend l'exemple d'un fichier test qui contient :
ligne1 -> 0
ligne2 -> 2
ligne3 -> 3
ligne4 -> 6
ligne5 -> 5
ligne6 -> 10

Je voudrais effectuer les soustractions pour obtenir :
ligne1 ->
ligne2 -> 2
ligne3 -> 1
ligne4 -> 3
ligne5 -> -1
ligne6 -> 5

Je vous remercie d'avance pour votre aide.

Bonne journée,
Martin

  • # awk

    Posté par  (site web personnel) . Évalué à 2. Dernière modification le 17 octobre 2019 à 15:59.

    Moi j'utiliserais awk, par contre je ne sais pas ce que tu veux afficher pour la première ligne une donc j'ai sauté celle ci.

    {
            LINES[NR] = $0
    }
    
    END {
            # printf nul pour ta première ligne ?
            for (i = 2; i <= NR; i++)
                    printf "%d\n", LINES[i] - LINES[i - 1]
    }

    À l'exécution (le contenu de data.txt est ta suite de numéro ligne par ligne, ni plus ni moins) :

    awk -f test.awk < data.txt
    2
    1
    3
    -1
    5
    

    Note : il y a peut-être une solution différente sans passer par un tableau temporaire.

    git is great because linus did it, mercurial is better because he didn't

    • [^] # Re: awk

      Posté par  . Évalué à 3. Dernière modification le 17 octobre 2019 à 16:49.

      Moi, je ferais le traitement ligne par ligne :

      (NR==0){ current = $1 }
      (NR!=0){
          old=current; 
          current=$1; 
          print current-old;
      }

      Le test :

      $ cat data.txt | awk -f filtre.awk
      2
      1
      3
      -1
      5
      $
      • [^] # Re: awk

        Posté par  (site web personnel) . Évalué à 1.

        Bien vu, j'avais jamais pensé à utiliser les variables directement dans la condition du filtre :-)

        git is great because linus did it, mercurial is better because he didn't

      • [^] # Re: awk

        Posté par  . Évalué à 1. Dernière modification le 17 octobre 2019 à 18:49.

        Les enregistrements sont numérotés à partir de 1. La première ligne de ton script n'a pas d'effet.

        Et je tique sur le 'old = current' en début de bloc. Je verrais plutôt ça à la fin du bloc ou même dans un bloc séparé en fin de script.

        Ca donnerait ça :

        { print $1 - old }
        
        { old = $1 }
        
        • [^] # Re: awk

          Posté par  . Évalué à 2.

          Yep, je voulais montrer que awk est adapté à exécuter le code ligne à ligne (c’est à mon sens toute ça force), tout en restant clair pour le néophyte et lui donner envie de s’y mettre.
          Ta solution écrit la première valeur du fichier dans la console alors qu’elle ne doit pas y être… d’après le post initial.

          Je vois d’ailleurs que j’ai également un bug… NR semble se numéroter à partir de 1 :'( oups :-p

          • [^] # Re: awk

            Posté par  . Évalué à 2.

            L'énoncé précise que la première ligne sortie doit être 0 ou le vide.

            • [^] # Re: awk

              Posté par  . Évalué à 3.

              Pffff ! je retourne bosser… pas sûr d’être efficace ;-) je devrais plutôt aller dormir.

              • [^] # Re: awk

                Posté par  . Évalué à 1.

                Il y a des jours comme ça !

                Tu as déjà lu "The AWK Programming Language" de Aho, Weinberger et Kernighan ?
                Une petite merveille.

                • [^] # Re: awk

                  Posté par  . Évalué à 2.

                  Non, je ne connaissais pas. Une recherche rapide sur google m’ammène ici, un peu cher ;-)
                  Sinon, un pdf est disponible sur archive.org, pas sûr que ce soit légal par contre.

                  Merci pour ma culture.

      • [^] # Re: awk

        Posté par  . Évalué à 2.

        $ cat data.txt | awk -f filtre.awk

        UUOC !

        • [^] # Re: awk

          Posté par  . Évalué à 2. Dernière modification le 18 octobre 2019 à 10:38.

          Je ne connaissais pas… merci, néanmoins…

          Le coût en ressource restant négligeable, je continuerai avec le cat.

          Mon excellente raison, c’est que j’aime avoir les entrées à gauche, enchaîner les filtres et mes sorties à droite. Sûrement une question d’habitude, mais je trouve ça plus clair visuellement.

          Même si là, on parle d’une seule commande, na ! :-p

          • [^] # Re: awk

            Posté par  (site web personnel) . Évalué à 2. Dernière modification le 24 octobre 2019 à 08:01.

            awk est fait pour traiter du fichier

            awk '{ print $0 }' input.csv
            

            Comme tu ferais pour un grep

            Is it a Bird? Is it a Plane?? No, it's Super Poil !!!

  • # TP ?

    Posté par  (site web personnel) . Évalué à 2. Dernière modification le 18 octobre 2019 à 07:30.

    Ca me rappelle un de mes premiers TP, c'est un algo hyper basique

    while read line; do my_code; done < my_file.txt te permettra de lire ton fichier ligne par ligne
    Trouve ensuite comment sauvegarder la valeur courante pour l'utiliser dans ta prochaine itération de ta boucle
    A toi de trouver quoi mettre dans my_code, dois tu afficher le résultat ou le stocker …

    Note selon ta version de Shell (bash ou autre), tu peux utiliser les opérateurs suivant pour faire des opérations
    i=$(( 1 + 1 ))
    i=$(expr 1 + 1)

    Note si c'est pour un TP et que tu n'es pas reconnu comme un Geek par tes pairs, je te déconseille de montrer une réalisation en awk sur tes premières semaines de cours XD

    Is it a Bird? Is it a Plane?? No, it's Super Poil !!!

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.