Script shell bash sur un texte

niceLP -  
hugnix Messages postés 129 Date d'inscription   Statut Membre -
j'ai un exo qui consiste à insérer une ligne en premier argument($1)
cette ligne doit se situer au milieu d'un texte déjà constitué d'un fichier existant , par exemple :

ligne 1
ligne2
nouvelle ligne
ligne 3
ligne4

on doit le faire sans utiliser les commandes sed et awk , en calculant les lignes ; j'ai fait comme ceci mais ça plante

lignes= wc -l $2 | cut -c1

milieu= $(($lignes/ 2))

si vous avez des idées , merci
Configuration: Windows XP
Firefox 1.5.0.11

54 réponses

  • 1
  • 2
  • 3
Résumé de la discussion

L’objectif consiste à insérer une ligne fournie en premier argument dans le milieu d’un fichier texte existant, sans recourir à sed ni awk, en calculant dynamiquement le point médian. La solution consiste à calculer le milieu à partir du nombre de lignes, puis à assembler le fichier avec head et tail autour de la ligne fournie, insérée entre les deux parties. Par exemple, on peut décrire le procédé comme le calcul du milieu puis la composition du fichier avec head et tail et l’insertion est effectuée via une redirection vers un fichier intermédiaire. En pratique, il peut être utile d’utiliser un fichier temporaire et de vérifier les permissions ou d’ajuster le calcul du milieu si le fichier est hybride (lignes vides, retours chariot).

Généré automatiquement par IA
sur la base des meilleures réponses
  1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    pourquoi pas
    root@debian:~# cat ccm.sh
    #!/bin/bash
    a=$(ls -l $1 | cut -d' ' -f1)
    b=${a//[rwx]/"\toui\t"}
    aa=${b//-/"\tnon\t"}
    user=$(ls -l $1 | cut -d ' ' -f3)
    groupe=$(ls -l $1 | cut -d ' ' -f4)
    u=${aa:7:21} g=${aa:21:21} o=${aa:42:21}
    echo -e "    \t\t\tread\t\twrite\t\texecute"
    echo -e "user $user\t$u\ngroupe $groupe\t$g\nautres\t\t$o"
    
    root@debian:~# sh ccm.sh ccm.sh
                            read            write           execute
    user root               oui             oui             non
    groupe lami20j          non             oui             non
    autres                  non             oui             non
    root@debian:~#
    
    2
  2. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Salut,
    [jp@MDK tmpfs]$ cat niceLP.sh
    #! /bin/bash
    
    echo "$1" > tmp
    milieu=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    split -l "$milieu" bar.txt tmp
    cat tmpaa tmp tmpab > fichier
    rm -f tmp*
    
    [jp@MDK tmpfs]$ sh niceLP.sh "Ligne introduite" bar.txt
    
    [jp@MDK tmpfs]$ cat fichier
    Ligne 1
    Ligne 2
    Ligne 3
    Ligne 4
    Ligne 5
    Ligne 6
    Ligne introduite
    Ligne 7
    Ligne 8
    Ligne 9
    Ligne 10
    Ligne 11
    Ligne 12
    [jp@MDK tmpfs]$ 
    Voir le "man split".

    ;-))

    Édit : La soluce à "lami20j" (enfin dans l'esprit je pense) :
    #! /bin/bash
    
    milieu=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    head -"$milieu" "$2" > fichier
    echo "$1" >> fichier
    tail -"$milieu" "$2" >> fichier
    
    1
    1. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
       
      Salut,

      Édit : La soluce à "lami20j" (enfin dans l'esprit je pense) :
      je confirme :-))
      Merci.
      0
  3. lami20j Messages postés 21506 Date d'inscription   Statut Modérateur, Contributeur sécurité Dernière intervention   3 571
     
    Salut,

    tu as le droit d'utiliser head ou tail?
    0
  4. niceLP
     
    oui on peut le faire avec les commandes tail et head , j'ai essayé mais ça ne marche pas , à chaque fois il me supprime les lignes du fichier ( fichier)
    pourtant j'ai bien mis les ">>" ; y a t il un pb avec le $milieu ?
    merci
    0
  5. Vous n’avez pas trouvé la réponse que vous recherchez ?

    Posez votre question
  6. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Copie/Colle ton script, ton fichier de référence et ton fichier de sortie. Merci.
    0
  7. niceLP
     
    voici le script
    ligneinsere

    #! /bin/bash

    centre=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    head -"$centre" "$2" > fichier
    echo "$1" >> fichier
    tail -"$centre" "$2" >> fichier

    execution :
    $ sh ligneinsere "ligne au milieu" fichier

    resultat
    ligne au milieu
    ligne au milieu
    0
  8. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Juste un truc : j'ai l'impression que tu lances ton script sur le fichier même faisant office de fichier de sortie, non ?

    Il faut que le fichier où tu vas lire les lignes soit différent du fichier où tu vas écrire la sortie !!!

    Peut être ne suis-je pas dans l'exactitude de la chose, dans ce cas là, sorry ;-(
    0
  9. niceLP
     
    ok tu as raison , désolé je prenais le meme fichier d'entrée et de sortie
    merci encore
    0
  10. hugnix
     
    bonjour a tous j'ai le même problème mais je l'ai résolu autrement bon c'est sur c'est quand même plus facile...

    head -3 fichier > temp

    echo ligne de texte >> temp

    tail -3 fichier >> temp

    cat temp > fichier

    rm temp

    cat fichier

    j'ai essayé d'analyser la soluce au dessus mais je bloque avec les variables j'ai pas tout compris, wc -l ok, mais aprés..........................

    A+
    0
  11. Simon
     
    quand le nombre de ligne est pair, ca fonctionne par contre quand c'est impair, il efface une ligne.

    pour faire un test en plus, je dois utiliser quoi ?
    0
  12. hugnix Messages postés 129 Date d'inscription   Statut Membre
     
    Salut,
    à mon avis, vu que la nombre de ligne est impair, il le coupe bien en deux mais en deux partie inégale 91/2=45,5 ce qui donne 46/45, tu me suis?
    Je t'ai trouvé ça, je pense que ça devrait te satisfaire, du moins je l'espère, sinon je peux te pondre un petit script qui peux te permettre de donné la valeur a head et a tail, bon c'est sur si ton fichier 351443134143142346 lignes, prévoit une calculette....

    #! /bin/bash

    centre1=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    centre2=$(($centre1 +1))
    head -"$centre" "$2" > fichier
    echo "$1" >> fichier
    tail -"$centre2" "$2" >> fichier

    Dsl pour le double post jipicy, j'ai voulu l'éditer mais tu m'as devancés de quelque secondes..............

    Merci pour eux ;)
    0
  13. makoko
     
    Bonjour,

    J'ai le même problème aussi. ta solution est intéressante, mais tu changes le nom du fichier; dans mon exo, on ne doit pas le changer !

    Alors je dois encore chercher la solution. je vais voir comment je peux changer ton script.

    Mais, bien sûr, si tu peux donner un coup de main, ça peut toujours accélérer les choses!

    Merci
    0
  14. makoko
     
    bonjour,

    Ce que je voudrais, c'est avec un fichier yo :

    eeeee
    eeeee
    eeeee
    eeeee

    Insérer au milieu : hello, en sautant une ligne ; cela devrait donner :

    eeeee
    eeeee
    hello
    eeeee
    eeeee

    Or, en essayant les scripts proposés, je n'arrive pas à ce résultat, soit

    -dans le script avec, head et tail , des lignes sont ajoutées ; ainsi j'obtiens : cat yo :

    eeeee
    eeeee
    eeeee
    eeeee
    hello
    eeeee
    eeeee
    eeeee

    Autrement dit, il me rajoute des lignes de texte, copies de lignes du texte, au texte

    Ou alors, rien ne change dans les deux fichiers : fichier et yo

    cat fichier :

    eeeee
    eeeee
    eeeee
    eeeee

    cat yo

    eeeee
    eeeee
    eeeee
    eeeee

    Je ne suis pas sorti de l'auberge !

    Merci tout de même

    ps : scripts de ref.:
    ---------------------------

    #! /bin/bash

    centre1=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    centre2=$(($centre1 +1))
    head -"$centre" "$2" > fichier
    echo "$1" >> fichier
    tail -"$centre2" "$2" >> fichier

    rem.: centre, n'est pas une variable. Or vous lui demandez une valeur!
    fichier, sort yo, et l'insertion 'hello' mais avec des copies de lignes en plus. ce qui fait que l'insertion n'apparait pas au milieu.
    ------------------------------------

    ! /bin/bash

    echo "$1" > tmp
    milieu=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    split -l "$milieu" bar.txt tmp
    cat tmpaa tmp tmpab > fichier
    rm -f tmp*

    rem.: fichier tmpaa,, tmpab, n'existent pas
    bar changé par mon fichier
    0
  15. makoko Messages postés 54 Statut Membre
     
    bonjour,

    J'obtiens bien ce que je voudrais avec ce script (logique): sh mo hello yo , mais pas où, il fallait.

    #! /bin/bash

    milieu=$(expr $(wc -l $2 | cut -d" " -f1) / 2)
    head -"$milieu" "$2" > fichier
    echo "$1" >> fichier
    tail -"$milieu" "$2" >> fichier

    cat yo

    eeeee
    eeeee
    eeeee
    eeeee

    donc, échec, toujours ....

    mais sur fichier : cat fichier :

    eeeee
    eeeee
    hello
    eeeee
    eeeee

    je voudrais ce résultat aussi dans yo!

    Je ne suis pas au bout du roulot ....

    merci
    0
  16. makoko Messages postés 54 Statut Membre
     
    Je l'ai eu !

    En partant du script de jipicy (le 2e), que je remercie au passage, plus simple et plus judicieux (le premier, j'ai eu du mal ,avec split!), j'ai demandé à la fin, tout simplement de 'mv fichier yo', et le tour (le tout aussi) était joué!

    j'avais enfin, non de dieu ! ce que je voulais :

    eeeee
    eeeee
    hello
    eeeee
    eeeee

    j'aurais du venir sur votre site plus tôt : seul, on a toujours plus de mal, malgré le cours et du matériel qu'on peut trouver ailleurs. Mais c'est dans l'échange "vive et animé", ou en collectif, qu'on avance, en testant les solutions, en les remaniant, en tentant de comprendre leur logique.

    j'ai passé la nuit entière là-dessus, mais cette fois, ça y est, j'ai enfin réussi. cela faisait des jours, que j'étais là-dessus, mais tout seul, pas facile, même si on avance un peu, mais pas autant que quand on est épaulé !

    Merci à vous, Merci aux contributeurs
    0
  17. makoko Messages postés 54 Statut Membre
     
    bonjour,

    je reviens vers vous, avec un problème, simple, mais je galère un peu ! je débute sérieusement sur unix.

    pb : je fais une redirection de 'env' sous unix, donc, je vais avoir : pwd, user, mail, logname, home.

    ex. : env > toi

    je souhaite sortir (extraire) et afficher, numéro de ligne, ), nom de l'occurence, = , chaque occurrence de user (l'utilisateur qui exécute le script) , de cette façon:

    1) pwd=
    2) user=
    jusqu'à
    4) home=

    et pouvoir aussi le faire autant de fois, que ces occurrences là, sont contenues dans le fichier : dans le cas, par ex., où je redirige plusieurs fois, env, dans le même fichier, toi.

    travail déjà effectué : j'ai essayé par ex. : find / -pwd 'toi' ( pour faire un premier test: décomposer tout pb, en pbs, plus simples), mais, j'ai eu le message d'erreur suivant :
    find: invalid predicate `-pwd'

    je continue la recherche.

    Merci pour votre aide d'avance
    0
  18. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Salut,

    Un truc dans ce genre :
    $ env | egrep "^(HOME|USER|PWD|SHELL)" | cat -n
         1  SHELL=/bin/bash
         2  USER=jp
         3  PWD=/home/jp/tmpfs
         4  HOME=/home/jp
    ;-))
    0
  19. makoko Messages postés 54 Statut Membre
     
    Bonjour,

    J'ai avancé. C'est grep, qu'il faut utiliser.
    J'ai redirigé 3 fois, ma sortie (env > toi (*3))

    Ainsi, j'obtiens :

    PWD=
    PWD=
    PWD=

    Ce que je veux, c'est :

    1) PWD=
    2) PWD=
    3) PWD=

    Et ceci pour les autres occurrences aussi, bien sûr : tout cela redirigé vers un fichier, dans un script.

    La recherche continue.

    Merci de votre contribution
    0
  20. hugnix Messages postés 129 Date d'inscription   Statut Membre
     
    Effectivement j'ai oublié de mettre une ligne... ormalement avec ça a la fin ton fichier garderas le même nom
    cat temp > $2 | rm temp 
    , par contre moi il le met bien au millieu, je viens de réessayer sur un fichier de onze ligne et ca donné ca

    11111111111111111
    11111111111111111
    11111111111111111
    11111111111111111
    11111111111111111
    00000000000000000
    11111111111111111
    11111111111111111
    11111111111111111
    11111111111111111
    11111111111111111
    11111111111111111

    Maintenant si tu essaye avec un des scripts au dessus ça devrait donner ça, normalement.

    1111111111111
    0000000000000
    2222222222222
    1111111111111

    Je précise que le script que j'ai posté ne fonctionne que pour un nombres de lignes impair, avec un nombre de ligne pair, les scripts proposé au dessus fonctionne très bien, le problème c'est que a chaque fois il faut connaitre le nombre de lignes, ce qui serait intéressant c'est d'essayer de faire un fichier qui insère une ligne au milieu sans tenir compte du fait que le nombre de lignes soit pair ou impair.

    "j'aurais du venir sur votre site plus tôt : seul, on a toujours plus de mal, malgré le cours et du matériel qu'on peut trouver ailleurs"
    Oui les gens ici sont toujours prés à t'aider si de ton coté te fait un p'tit quelquechose, donc ceux qui attendent d'avoir une réponse toute cuite se gourre un peu, et c'est bien, c'est comme ça que l'on apprend, et si t'as des problémes pour tes scripts jipicy seras là :)))))) il m'as pas mal aidé pour mon script du jeu du pendu , si tu veux y jeter un coup d'oeil http://www.commentcamarche.net/forum/affich 3900064 script bash avance#0 regarde a la fin j'ai posté une version final, mais j y ai retrouvé quelque petites erreurs mais en gros ça marche comme il faut.

    Pour ton autre exercices le résultat final ce serait pas un truc du genre?

    1) PWD=/home/toi
    2) USER=toi
    3) MAIL=/var/spool/mail/toi
    4) LOGNAME=toi
    5) HOME=/home/toi
    ...

    Parce que j'ai du faire un exercice dans le même genre, j'avais la commande env redirigé 5 fois dans le fichier XX et je devais y rajouter le numero de la ligne plus une paranthése, donc si t'as besoin.... mais je pense que la soluce de jipicy devrait te satisfaire!?
    0
  21. jipicy Messages postés 40842 Date d'inscription   Statut Modérateur Dernière intervention   4 898
     
    Tiens, j'ai mieux encore :
    $ env | egrep "^(HOME|USER|PWD|SHELL)" | nl -w 1 -s ") "
    1) SHELL=/bin/bash
    2) USER=jp
    3) PWD=/home/jp/tmpfs
    4) HOME=/home/jp
    ;-))
    0
  • 1
  • 2
  • 3