Shell lire et modifier une ligne précise

Résolu
Bonjour à toutes et à tous,

Voici mon fichier par exemple :

1,0000 0,673 0,005
2,0000 0,790 0,009
3,0000 0,787 0,018
4,0000 0,787 0,010
5,0000 0,792 0,016

je souhaite modifier la valeur "0,787" par "toto" par exemple mais uniquement sur la ligne 4.
En faisant : sed -i "s/"0,787"/"toto"/g" test.txt
il modifie toutes les lignes.

Comment puis je restreindre a la ligne 4 svp?

Merci d'avance
Sony
Configuration: Linux
Firefox 3.0.10

19 réponses

  • Votes
  • Date
  • Date décroissante
  1. Modérateur
    Salut,
    [tmpfs]$ cat plop
    1,0000 0,673 0,005
    2,0000 0,790 0,009
    3,0000 0,787 0,018
    4,0000 0,787 0,010
    5,0000 0,792 0,016
    
    [tmpfs]$ sed '4 s/0,787/toto/' plop
    1,0000 0,673 0,005
    2,0000 0,790 0,009
    3,0000 0,787 0,018
    4,0000 toto 0,010
    5,0000 0,792 0,016
    
    [tmpfs]$
    ;-))
    1. Salut merci pour la reponse.

      En faisant cela je vois les modifs dans la console mais le fichier ne se modifie pas. Est ce normal?

      Sony
    2. Modérateur
      @sony97oneIl suffit de remettre l'option "-i" ;-))
  2. Contributeur
    essaye ce code.
    for(n=1;n<=NF;n++)x +=$n : on somme avec chaque champ de chaque ligne
    m+=NF : en sommant le nombre de champs, on a à la fin le nombre total de nombres
    BEGIN { x = 0 ;m = 0} : ces lignes sont superflues puisque les variables sont par défaut =0
    je n'ai pas utilisé /,/./ ; essaye
    export LC_NUMERIC="en_US.UTF-8"
    au début du script pour n'afficher que des points dans les calculs décimaux

    #!/bin/bash
    
    for file in *.txt
    do
    
    moyenne=$(awk '
    BEGIN { x = 0 ;m = 0}
    {for(n=1;n<=NF;n++)x +=$n; m+=NF}
    END {
    moy= x / m
    printf "%.2f\n", moy
    }' "$file")
    
    ecart=$(awk -v moyenne=${moyenne} '
    BEGIN { x = 0 ; m = 0}
    {for(n=1;n<=NF;n++)x +=( $n - moyenne ) ^ 2; m+=NF}
    END {
    ecar= ( x / m) ^ 0.50
    printf "%.2f\n",ecar
    }' "$file")
    
    echo "${file}${moyenne},${ecart}" >> fichier.sortie
    done
    
    1. Arf encore moi avec un petit problème dans la même lignée...

      Voilà.

      J'ai un code fortran CONTNM.f :

      1) SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)
      2)
      3) PARAMETER(MAXCLY=40)
      4) .....
      ...) .....

      Je souhaite modifier la valeur de MAXCLY avant de compiler avec un script :

      #! /bin/bash

      echo "MAXCLY"
      read nb
      sed -i '3 s/40/'$nb'/' CONTNM.f

      La où j'ai pas fait gaffe c'est que maintenant MAXCLY=nb et que si je veux encore modifier sa valeur je dois modifier le script au niveau du sed.

      Comment faire pour que le script écrivent MAXCLY=nb avec nb definit par l'utilisateur?

      Je vous remercie d'avance,
      Sony
      1. Modérateur
        [tmpfs]$ cat plop
        1) SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)
        2)
        3) PARAMETER(MAXCLY=40)
        4) .....
        ...) .....
        
        [tmpfs]$ read nb
        31000
        
        [tmpfs]$ sed "3 s/40/$nb/" plop
        1) SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)
        2)
        3) PARAMETER(MAXCLY=31000)
        4) .....
        ...) .....
        
        [tmpfs]$
        Voir dans la FAQ : SED - Le remplacement de variable

        ;-))
        1. ok mais comment lire la valeur 40 svp?

          Sony
          1. Modérateur
            Comme ça :
            sed "3 s/\(.*=\).*/\1$nb)/"
            ;-))
        2. Après essai (juste sed -i "3 s/\(.*=\).*/\1$nb)/") cela ne fonctionne pas. Il me retourne un blanc et efface la valeur 40...

          l'idée est de lire cette valeur (40) pour la modifier par une valeur définit par l'utilisateur...

          1) SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)
          2)
          3) PARAMETER(MAXCLY=40)
          4) .....
          ...) .....

          **************************************************************
          #! /bin/bash

          echo "Nombre de couches"
          read np
          sed -i "3 s/\(.*=\).*/\1$nb)/" CONTNM.f
          sed -i "3 s/$nb/$np/" CONTNM.f

          Bien à vous,
          Sony
          1. PS : les 1) ,2) sont mis juste pour préciser les numéros de ligne, ils n'apparaissent pas dans le fichier.

            SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)

            PARAMETER(MAXCLY=40)

            Sony
            1. Modérateur
              [tmpfs]$ cat plop
              SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)
              
              PARAMETER(MAXCLY=40)
              bla bla bla
              bla bla bla
              
              [tmpfs]$ read nb
              222
              
              [tmpfs]$ sed "3 s/\(.*=\).*/\1$nb)/" plop
              SUBROUTINE ABSCNT(FREQ,J,TT,ABSCNTO3)
              
              PARAMETER(MAXCLY=222)
              bla bla bla
              bla bla bla
              
              [tmpfs]$
              ;-))
              1. Salut,

                J'ai un prob avec la commande SED.

                J'ai un programme fortran a exécuté sur une centaine de fichier. Donc je suis amené a modifier le nom du fichier d'entrée dans ce programme fortran.
                J'ai donc fait ce petit script qui lit le nom du fichier *.dat et créé un fichier de sortie *.txt.

                Mon probleme c'est qu'il n'écrit pas les noms quand je fais:
                sed -i "11 s/\(.*=\).*/\1$m)/" pickout.f
                sed -i "12 s/\(.*=\).*/\1$n)/" pickout.f

                Votre sera très appréciable

                MERCI!!!

                ***************
                ***************
                Voici mon script:

                #! /bin/bash

                for file in *.dat
                do

                n=$ echo $file
                m=$ echo "$file" | sed "s/dat/txt/"

                echo $n
                echo $m

                sed -i "11 s/\(.*=\).*/\1$m)/" pickout.f
                sed -i "12 s/\(.*=\).*/\1$n)/" pickout.f

                f77 pickout.f -o pickout
                ./pickout

                done
                ******************
                ******************
                et mon prog fortran pickout.f :

                PROGRAM pickout
                INTEGER ilig, icol, idimlig, idimcol
                DIMENSION rad(2399)
                c Entrer la dimension colonne-ligne des images.
                idimcol=2399
                idimlig=1674
                c Entrer la position colonne-ligne de la cible.
                icol=870
                ilig=906
                c Lecture images et ecriture tableau.
                (11) OPEN(4,FILE=)
                (12) OPEN(1,FILE=)
                &ACCESS='direct',RECL=4*idimcol,FORM='unformatted',STATUS=)
                DO k=ilig-2,ilig+2
                READ(1,REC=k) (rad(ic),ic=1,idimcol)
                WRITE(4,100) (rad(ic),ic=icol-2,icol+2)
                ENDDO
                100 format(5(F9.4,x))
                CLOSE(1)
                CLOSE(4)
                END
                1. Contributeur
                  hello
                  change
                  n=$ echo $file
                  m=$ echo "$file" | sed "s/dat/txt/"
                  par
                  n=$file
                  m=$(echo "$file" | sed "s/dat/txt/")
                  1. merci ca marche!

                    quelle est la difference entre:

                    n=$ echo $file et n=$file
                    1. Contributeur
                      n=$file # j'assigne à n la valeur de la variable file

                      n=$ echo $file # j'assigne à n $ puis j'exécute echo $file

                      n=$(echo $file) # ceci est l'équivalent de n=$file
                      1. voici les noms de fichier à l'issu de l'execution de pickout:

                        MSG1-SEVI-MSG15-0100-NA-200611160227LST.txt
                        MSG1-SEVI-MSG15-0100-NA-200611160242LST.txt

                        etc...

                        contenant chacun un tableau 5*5 de la forme:

                        312.9490 313.6078 313.6268 313.2100 313.3503
                        313.3282 313.2675 314.1463 313.6644 313.6580
                        312.6511 314.0935 313.6562 313.0982 313.2926
                        312.7724 312.0528 312.3088 313.1470 312.7823
                        312.4456 311.9125 312.0738 312.5998 311.8029

                        Comment lire tout ces fichiers, faire la moyenne et l'ecartype de leur contenu et l'ecrire dans un fichier de sortie.

                        par exemple:

                        200611160227 [moyenne] [ecartype]
                        200611160242 [moyenne] [ecartype]
                        ect...

                        j'ai fais ca mais cela n'a pas l'air de fonctionner.

                        Merci d'avance

                        #! /bin/bash

                        for file in *.txt
                        do
                        name=$file

                        moyenne=$(cat "$file" | awk '
                        BEGIN {
                        FS=" "
                        x = 0
                        }
                        NR==1 , NR==$FNR {
                        x=x+$2
                        }
                        END {
                        moy= ( x / ( FNR - 1 ) )
                        printf "%.2f\n",moy
                        }')

                        ecart=$(cat "$file" | awk '
                        BEGIN {
                        FS=" "
                        x = 0
                        }
                        NR==1 , NR==$FNR {
                        x= x + ( $2 - '"${moyenne/,/.}"' ) ^ 2
                        }
                        END {
                        ecar= ( x / ( FNR - 1 ) ) ^ 0.50
                        printf "%.2f\n",ecar
                        }')

                        echo "${name}${moyenne/,/.},${ecart/,/.}" >> fichier.sortie
                        done
                        1. Contributeur
                          faire la moyenne et l'ecartype
                          de quoi ? chaque colonne , de tout les nombres d'un fichier, de la colonne 2 ?
                          1. salut ca a l'air de fonctionner.

                            J'ai fais qqes controle a la main et je me suis rendu compte d'un erreur sur la valeur de l'ecartype... ca doit etre du a la precision numerique des valeurs?

                            MERCI
                            1. Contributeur
                              essaye d'imprimer plus de décimales
                              printf "%.8f\n", moy

                              printf "%.8f\n",ecar
                              1. ah ben c'etait une erreur de formule

                                ecar= ( x / (m-1)) ^ 0.50

                                et pas

                                ecar= ( x / m) ^ 0.50

                                Pb resolu merci.