Pb script middleline

Résolu
bonjour je souhaite faire un script sous unix qui m'insère une phrase au milieu d'un texte d'un autre fichier, tout en conservant le nom du fichier texte. Je ne dois ni utiliser sed ni awk.
J'ai pensé travailler avec des fichiers temporaires, l'un pour stocker la première partie du texte, l'autre pour la deuxième partie
Ensuite je veux insérer ma phrase saisie en arg1 dans le premier fichier temp.
Puis pour finir recoller les deux fichier temp pour me redonner le fichier texte complet donné en arg2, avec la ligne insérer au milieu.

voici mon script:

#!/bin/bash
#script pour inserer une ligne au milieu d'un texte

#recuperation des arguments dans des variables
arg1=$1 #la phrase saisie
arg2=$2 #le fichier texte
x=$(wc-l $2) # le nombre de ligne dans le fichier <= j'ai une erreur ici
middle= $(($x/2)) <= j'ai aussi une erreur ici
debut=$x-$middle #nombre de lignes dans la premiere partie du texte
fin=$x-$debut #nombre de lignes dans la seconde partie du texte

#Copie, s'il existe, du contenu du fichier passe en argument dans 2 fichiers
#temp1 et temp2
cat $( head -$debut $arg2 ) > temp1.txt
cat $( tail -$fin $arg2) > temp2.txt

# Affichage de l'argument 1 tout en redirigeant la sortie standard vers le
#fichier temp de debut
echo $arg1 >> temp1.txt

# Ajout a la fin du fichier temp de debut le fichier temp de fin
cat temp2.txt >> temp1.txt
cat temp1.txt > $arg2
rm temp1.txt temp2.txt
cat $arg1

Pouvez-vous me dire ce qu'il ne va pas dans mon script, ou pouvez-vous me proposer une solution sur une autre démarche à suivre.
Merci.
Configuration: Windows XP
Firefox 2.0.0.6

16 réponses

  1. Modérateur
    #! /bin/bash
    
    ligne=$(expr $(wc -l $2 | cut -d " " -f1))
    
    case "$ligne" in
    *[02468])       middle=$(expr $(wc -l $2 | cut -d " " -f1) / 2)
                    debut=$(head -"$middle" "$2")
                    fin=$(tail -"$middle" "$2")
                    ;;
    *[13579])       middle=$(expr $(wc -l $2 | cut -d " " -f1) / 2)
                    middles=$(expr $middle + 1)
                    debut=$(head -"$middles" "$2")
                    fin=$(tail -"$middle" "$2")
                    ;;
    *)              echo "Error"
                    exit
                    ;;
    esac
    
    echo "$debut" > $2
    echo "$1" >> "$2"
    echo "$fin" >> "$2"
    cat "$2"
    
    ;-))
    1. c'est ok cette fois, excepté que je ne parviens pas à gérer un nombre de lignes impair. C'est à dire que ça marche que pour un nombre de lignes pair, sinon, la ligne insérée écrase la ligne actuelle du milieu du texte.
      1. Modérateur
        Modifie ton script comme ci-dessous. En gras les lignes modifiées en italique les anciennes....
        #!/bin/bash
        #script pour inserer une ligne au milieu d'un texte
        
        #recuperation des arguments dans des variables
        #+ arg=$1 #la phrase saisie
        arg1=$1 #la phrase saisie
        arg2=$2 #le fichier texte
        
        #middle of monText.txt
        middle=$(expr $(wc -l $2 | cut -d " " -f1) / 2)
        
        #begin=number of lines in the first part of monTexte, then insert it in temp1
        debut=$(head -"$middle" "$arg2")
        #+ echo $debut > temp1
        echo "$debut" > temp1
        #+ echo $arg1 >> temp1 
        echo "$arg1" >> temp1 #here insert the arg1 at the end of temp1
        
        #end=number of lines in the second part of monTexte, then insert it in temp2
        fin=$(tail -"$middle" "$arg2")
        #+ echo $fin > temp2
        echo "$fin" > temp2
        
        #+ echo $temp1 > $arg2
        cat temp1 > "$arg2" #replace content of arg2 by temp1
        #+ echo $temp2 >> $arg2
        cat temp2 >> "$arg2" #insert temp2 at the end of arg2
        
        rm temp1 temp2
        ;-))
        1. voici mon script actuellement. Le problème que je recontre maintenant c'est que je ne parviens pas à concaténer les 2 fichiers temp, et surtout mon fichier texte se vide alors qu'il contenait quelque chose.

          #!/bin/bash
          #script pour inserer une ligne au milieu d'un texte

          #recuperation des arguments dans des variables
          arg=$1 #la phrase saisie
          arg2=$2 #le fichier texte

          #middle of monText.txt
          middle=$(expr $(wc -l $2 | cut -d " " -f1) / 2)

          #begin=number of lines in the first part of monTexte, then insert it in temp1
          debut=$(head -"$middle" "$arg2")
          echo $debut > temp1
          echo $arg1 >> temp1 #here insert the arg1 at the end of temp1

          #end=number of lines in the second part of monTexte, then insert it in temp2
          fin=$(tail -"$middle" "$arg2")
          echo $fin > temp2

          echo $temp1 > $arg2 #replace content of arg2 by temp1
          echo $temp2 >> $arg2 #insert temp2 at the end of arg2

          rm temp1 temp2
          1. Modérateur
            Tu peux afficher ton code dans son intégralité s'il te plait, merci. (colle-le avec le bouton de mise en forme qu'on voit bien si la syntaxe et tous les espaces sont bien respectés).
            1. après les modifications que tu m'as suggérés, voilà ce que me dit le prompt:

              [belkacem.berbache@unix chapter7]$ sh middleline "salut tous" monText
              middleline: line 7: wc-l: command not found
              expr: syntax error
              cat: salut: No such file or directory
              cat: tous: No such file or directory
              tail: unrecognized option `---'
              Try `tail --help' for more information.
              1. Pourrais-tu m'expliquer -f1 et -f2, je ne comprends pas. Ce sont des champ, mais quels champs? est-ce que tu veux parler des arguments $1 et $2??
                1. Modérateur
                  Non, on parle des champs contenus dans le résultat de la commande "wc -l" qui te renvoie :
                  10 fich.txt
                  autrement dit, si on considère (et on le considère vu qu'on l'a défini par '-d " "') l'espace entre le nombre 10 et le nom du fichier fich.txt comme caractère séparateur, il y a effectivement 2 champs (un de chaque côté de l'espace), affichables par la commande par -f1 ou -f2.

                  Dans une phrase où le caractère séparateur est l'espace, chaque mot de cette phrase correspond à 1 champ et peut être mis en correspondance par la valeur de son champ.
              2. Modérateur
                Le problème vient du fait qu'on est parti sur un nombre de ligne "pair" et que maintenant avec la ligne rajoutée le nombre de ligne du fichier est "impair", de ce fait la division est arrondie au chiffre inférieur ce qui scinde le fichier au même endroit.

                Là par contre ça va pas être coton à gérer ;-((
                1. ton script fonctionne très bien. juste un soucis, c'est qu'en relancçant le script, il m'écrase la ligne inséréé précédement pour m'insérer la nouvelle ligne saisie en paramètre. C'est gênant car je ne peux pas rajouter de ligne de ce fait à mon texte. Ne serait-il pas mieux d'utiliser des fichier temp pour éviter ce pb? et comment le faire à partir de ton script?
                  1. Modérateur
                    $ wc -l fich.txt   # ta commande à toi
                      
                    10 fich.txt   # qui affiche le nbr de ligne et le nom du fichier
                    
                    $ wc -l fich.txt | cut -d " " -f1   # la commande "cut" coupe en fonction 
                                                                   # du délimiteur (d " ") 
                                                                   # et affiche le champ spécifié (-f1)
                    
                    10   # on affiche bien le 1er champ
                    
                    $ wc -l fich.txt | cut -d " " -f2   # là on demande d'afficher le second champ (-f2)
                    
                    fich.txt   # le résultat est bien le fichier
                    
                    $
                    ;-))
                    1. cette solution me convient. Seulement peux-tu m'expliquer ce que (wc -l $2 | cut -d " " -f1) produit? enfin après le pipe car je ne connais pas la commande cut -d. Merci jipicy
                      1. cut sert à découper une chaine.
                        L'option -d te permet de définir le délimiteur (Ici " " soit espace).
                        L'option -f te permet de choisir le "field" à extraire.
                        Donc dans ce cas, on découpe le premier champ avant l'espace
                    2. Modérateur
                      Salut,

                      Une façon de faire :
                      [tmpfs]$ cat fich.txt
                      
                      ligne 1
                      ligne 2
                      ligne 3
                      ligne 4
                      ligne 5
                      ligne 6
                      ligne 7
                      ligne 8
                      ligne 9
                      ligne 10
                      
                      [tmpfs]$ cat foo.sh
                      
                      #! /bin/bash
                      
                      middle=$(expr $(wc -l $2 | cut -d " " -f1) / 2)
                      debut=$(head -"$middle" "$2")
                      fin=$(tail -"$middle" "$2")
                      echo "$debut" > $2
                      echo "$1" >> "$2"
                      echo "$fin" >> "$2"
                      
                      [tmpfs]$ ./foo.sh "ligne insérée" fich.txt
                      
                      [tmpfs]$ cat fich.txt
                      
                      ligne 1
                      ligne 2
                      ligne 3
                      ligne 4
                      ligne 5
                      ligne insérée
                      ligne 6
                      ligne 7
                      ligne 8
                      ligne 9
                      ligne 10
                      
                      [tmpfs]$
                      ;-))
                      1. après les modifications que tu m'as suggérés, voilà ce que me dit le prompt:

                        [belkacem.berbache@unix chapter7]$ sh middleline "salut tous" monText
                        middleline: line 7: wc-l: command not found
                        expr: syntax error
                        cat: salut: No such file or directory
                        cat: tous: No such file or directory
                        tail: unrecognized option `---'
                        Try `tail --help' for more information.
                        1. x=$(wc-l $2)
                          devient
                          x=`wc-l $2`

                          Pour expr, je ne me souviens plus exactement de la syntaxe mais c'est quelque-chose comme :
                          middle= $(($x/2))
                          devient
                          middle=`expr $x / 2`

                          Et attention à ne pas laisser d'espaces autour du = quand tu affectes des variables. Le Shell UNIX est sensible à la casse mais aussi aux espaces...
                          1. Modérateur
                            Salut,

                            x=$(wc-l $2) est tout simplement la forme moderne de x=`wc-l $2`, beaucoup plus lisible et recommandée.

                            Il en est de même pour $(($x/2)) qui doit supplanter `expr $x / 2` (qui peut aussi s'écrire "$(expr $x / 2)").

                            ;-))
                        2. je vois pas très bien comment mettre en place ce que tu m'as dit. J'ai quand même les ereurs. Peut-être je ne les place pas au bon endroit?
                          Pourrais-tu être plus explicite? merci Chacual
                          1. Erreur 1 :
                            Quand tu veux renseigner une variable avec le résultat d'une commande, tu dois mettre ta commande entre quotes `` (Alt Gr + 7) et non pas entre accolades.

                            Erreur 2 :
                            $x/2 ne fonctionne pas !!
                            Si tu veux effectuer des calculs arithmétiques, tu dois utiliser la commande expr et suivre la remarque ci-dessus (``).

                            Dis-moi si tu ne t'en sors pas !