Forum Programmation.shell inserer un espace dans une sortie de 'cut'

Posté par  .
Étiquettes : aucune
1
23
août
2009
Bonjour a tous,

une requete probablement deja soulevee: j'ai a sortir des informations d'un fichier texte. Plusieurs infos par ligne. J'ai pour cela lancer une commande cut:

cut -c"22-25,47-55,56-64" 'source' > sortie

Ca marche, sans soucis. Mais ce n'est pas tres lisible car cut me colle les bouts coupes sans delimitation. J'ai bien essaye de mettre une option --output-delimiter mais rien n'y fait...

Existe-t'il un moyen d'inserer des espaces (ou tout autre caractere) entre les mots que j'extrais ?

Sinon je pensais a utiliser sed sur ma sortie, mais je ne sais pas si sed peut inserer des elements. Malheureusement, en temps que neophyte, je ne connais ni sed ni awk (qui devrait aussi faire l'affaire...).

Merci d'avance et bonne journee

Note: tout ceci est inclus dans une boucle en csh.
  • # pourtant

    Posté par  . Évalué à 2.

    tu peux poster ta ligne de cut avec ton output delimiter qui ne fonctionne pas ?

    parce que chezmoisamarche:

    $ echo "aaa" | cut -c1,2,3 --output-delimiter="|"
    a|a|a
    • [^] # Re: pourtant

      Posté par  . Évalué à 2.

      bah tout pareil que toi, gaaaaaAab:

      cut -c"22-25, 47-55,56-64,71-73,74-80" --output-delimiter=" " sp1 > fsp$i

      quand je fais un more de fsp$i, il n'y a pas d'espace entre les champs qui ont ete coupes.

      Pire: j'ai simplement fait la meme commande que toi ($echo aaa...="|") dans un terminal, et je trouve 'aaa' en sortie !!!

      La, ca commence a devenir grave... A croire que l'option '--output-delimiter' de cut n'est pas valable sur ma machine. Gluuupssss....

      Je suis "monte" en RedHat Enterprise 4.3as

      Y aurait-il un lien ?

      Merci quand meme
      • [^] # Re: pourtant

        Posté par  . Évalué à 8.

        bon, on peut dégainer du sed alors, mais ça va pas être très lisible ...
        Par exemple, pour les intervalles de ta question de départ ("22-25,47-55,56-64")

        $ echo 1234567890abcdefghijABCDEFGHIJ1234567890abcdefghijABCDEFGHIJ1234567890 |cut -c"22-25,47-55,56-64"
        BCDEghijABCDEFGHIJ1234


        D'après ton propre aveu, tu n'es pas une grosse brute en sed, on va donc construire la commande pas à pas. Tu peux aller te faire peur en allant direct à la fin du commentaire, mais une fois que tu auras lu ce petit pavé, ça devrait être claire comme de l'eau à peine croupie ;)

        On va utiliser sed suivant la syntaxe suivante :
        sed -e 's/<pattern>/<replacement>/'
        qui permet d'appliquer une regex. Dans cette regex, il faut définir un motif capable de représenter les découpes qu'on veut faire dans la ligne de départ.

        rapidement :
        ^ symbolise le début de ligne
        . remplace une occurence d'un caractère quelconque
        { et } permettent de "compter" des motifs
        ( et ) permettent d'extraire les bouts de lignes pour les réutiliser dans la chaîne de remplacement.
        * match n occurences du motif qu'il suit.

        Pour le motif de recherche, on peut construire quelque chose comme:
        ^.{21}(.{4}).{21}(.{9})(.{9}).*
        le .* à la fin représente la fin de la ligne (tous les caractères entre la position 65 et la fin de ligne)

        Pour la chaîne de remplacement, c'est beaucoup plus simple. On va utiliser une série de chiffres représentant le numéro du motif entre parenthèse de la chaîne de recherche. Autrement dit, 1 va correspondre au groupe de 4 caractère, 2, au premier groupe de 9 et 3 au second groupe de 9.

        on aura quelquechose comme :
        sed -e 's/^.{21}(.{4}).{21}(.{9})(.{9}).*/1 2 3/'

        sauf que j'ai légèrement simplifié. Les chiffres représentants les blocs entre parenthèses dans le motif de remplacement doivent être échappés par un \, sinon, ils représentent simplement des chiffres.
        sed -e 's/^.{21}(.{4}).{21}(.{9})(.{9}).*/\1 \2 \3/'

        et même qu'en fait, j'avais beaucoup simplifié, parce qu'il faut aussi échapper les accolades et les parenthèses, et d'un seul coup, c'est le bordel :

        $ echo 1234567890abcdefghijABCDEFGHIJ1234567890abcdefghijABCDEFGHIJ1234567890 | sed -e 's/^.\{21\}\(.\{4\}\).\{21\}\(.\{9\}\)\(.\{9\}\).*/\1 \2 \3/'
        BCDE ghijABCDE FGHIJ1234


        bref, sur le principe, pas très compliqué de faire ça en sed, mais pas très lisible ...
        Je dirais même que ça doit être plus lisible avec un one liner en perl :D

        bon, ça n'explique pas pourquoi ton cut n'applique pas l'ouput delimiter.
        • [^] # Re: pourtant

          Posté par  . Évalué à 3.

          moymoymoymoy... va falloir que je digere tout ca ! -en meme temps, ca va me filer quelques bases pour pouvoir (enfin) pondre du sed-

          Comme tu dis, c'est pas tres complique, c'est juste une suite de hieroglyphes. ; )

          Alors je vais tenter la dite commande, histoire de me faire la main.

          Pour resumer:
          -1ere accolade = nbre de caractere avant de "sed"
          -(.{x}) = nbr de caractere a "seder"
          -/\Y = Y est ce qui est extrait de la commande d'avant (peut surement provenir d'une autre source dans un script...)
          > je suppose que c'est derriere que tu as coller l'espace qu'il me manque
          -placer des \ pour que sed reconnaisse des "variables" (si j'ose m'exprimer).


          J'ai bon ? C'est bien de demander une reponse, mais c'est toujours mieux de la comprendre !! : )


          En tout cas merci du coup de main. Je vomis tout ca dans ma boucle et je reviens.


          Et pour le cut, je vais voir avec les IT qui m'ont installe RH...
        • [^] # Re: pourtant

          Posté par  . Évalué à -1.

          moymoymoymoy... va falloir que je digere tout ca ! -en meme temps, ca va me filer quelques bases pour pouvoir (enfin) pondre du sed-

          Comme tu dis, c'est pas tres complique, c'est juste une suite de hieroglyphes. ; )

          Alors je vais tenter la dite commande, histoire de me faire la main.

          Pour resumer:
          -1ere accolade = nbre de caractere avant de "sed"
          -(.{x}) = nbr de caractere a "seder"
          -/\Y = Y est ce qui est extrait de la commande d'avant (peut surement provenir d'une autre source dans un script...)
          > je suppose que c'est derriere que tu as coller l'espace qu'il me manque
          -placer des \ pour que sed reconnaisse des "variables" (si j'ose m'exprimer).


          J'ai bon ? C'est bien de demander une reponse, mais c'est toujours mieux de la comprendre !! : )


          En tout cas merci du coup de main. Je vomis tout ca dans ma boucle et je reviens.


          Et pour le cut, je vais voir avec les IT qui m'ont installe RH...
        • [^] # Re: pourtant

          Posté par  . Évalué à 2.

          En perl j'ai trouvé ça :
          echo 1234567890abcdefghijABCDEFGHIJ1234567890abcdefghijABCDEFGHIJ1234567890 | perl -E 'say substr($_, 21, 4), " ", substr($_, 47, 9), " ", substr($_, 55, 9)'

          C'est légèrement plus verbeux que le awk.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # ???

    Posté par  . Évalué à 2.

    pour moi ça fonctionne :[code]echo $0
    bash
    cat test.dat
    S 192.168.1.4 60477 208.80.152.2 8080
    S 192.168.1.4 60477 208.80.152.2 8080
    S 192.168.1.4 60477 208.80.152.2 8080
    S 192.168.1.4 60477 208.80.152.2 8080
    S 192.168.1.4 60477 208.80.152.2 8080
    cut --output-delimiter=' -- ' -c'3-5,7-10,15-' $dat
    192 -- 168. -- 60477 208.80.152.2 8080
    192 -- 168. -- 60477 208.80.152.2 8080
    192 -- 168. -- 60477 208.80.152.2 8080
    192 -- 168. -- 60477 208.80.152.2 8080
    192 -- 168. -- 60477 208.80.152.2 8080[/code]
  • # Pour awk

    Posté par  . Évalué à 1.

    Tu n'a vraiment pas de délimiteur dans ton fichier initial ?
    Si tu n'en a pas je ne suis pas sûr qu'awk puisse t'aider.

    Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

    • [^] # Re: Pour awk

      Posté par  . Évalué à 4.

      je viens de jeter un oeil au man. En fait, si, on peut en awk, et c'est en fait beaucoup plus simple (donc beaucoup moins rigolo ;) qu'en sed ...
      pour reprendre mon exemple précédent :
      echo $ echo 1234567890abcdefghijABCDEFGHIJ1234567890abcdefghijABCDEFGHIJ1234567890 |awk '{print substr($0, 22, 4) " " substr($0,47, 9) " " substr($0,56,9)}'
      BCDE ghijABCDE FGHIJ1234
      • [^] # Re: Pour awk

        Posté par  . Évalué à 1.

        J'avais pas pensé à sustr() trop l'habitude de faire un -F : '{ print $1 $2 }'.

        Merci beaucoup pour l'astuce :)

        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

        • [^] # Re: Pour awk

          Posté par  . Évalué à 1.

          eh beh eh beh messieurs,

          quel honneur pour un modeste posteur d'avoir tout plein de reponses. Merci !

          Un collegue m'a sortie une commande sed longue comme un bras, mais l'avantage, c'est qu'il a arrange la mise en page !

          Ca donne ca:

          sed -e 's/^.\{1\}\(.\{9\}\).\{11\}\(.\{4\}\).\{21\}\(.\{9\}\)\(.\{9\}\).*/Line \1 SP.\2 X = \3 Y = \4/'

          ca me sort un truc du genre:
          $Line 123456789 SP.ABCD X = 123456.89 Y = ABCDEF.GH

          S'il m'avait dit ca avant, je ne vous aurais pas embeter...

          Mais comme maintenant vous avez pondu des lignes en awk et en perl, j'ai plus qu'a m'y mettre !

          Merci encore
          • [^] # Re: Pour awk

            Posté par  . Évalué à 2.

            J'adore ce genre de questions ça me permet de revoir sed, awk et perl.

            C'est parfois bien utile.

            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

      • [^] # Re: Pour awk

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


        awk '{print substr($0, 22, 4) " " substr($0,47, 9) " " substr($0,56,9)}'


        Tu peux mettre des virgules pour faire les espaces. C'est plus élégant.

        awk '{print substr($0, 22, 4),substr($0,47, 9),substr($0,56,9)}'

Suivre le flux des commentaires

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