Help pour SED

Help pour SED - Shell/Batch - Programmation

Marsh Posté le 08-02-2007 à 08:54:19    

Bonjour, j'ai un problème avec sed.
 
voilà ce que je veux faire:
 
fichier1 contient:
 
| AGF                            |    MJ0 |   MOPB4TSMSV-01 |
| AGF                            |    MJ0 |   MOPB4TSMSV-01 |
| AGS                            |    FA3 |   MOPB4TSMSV-05 |
| AIR_LIQUIDE                    |    L02 |   MOPB2TSMSV-01 |
| ALC_EVILOG                     |    TY3 |   MOPB2TSMSV-03 |
| ALC_INFOR                      |    A39 |   MOPB2TSMSV-03 |
| ALC_IPNERGIE                   |    GE1 |   MOPB2TSMSV-03 |
| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| ARKEMA                         |    RK0 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-03 |

| ASPAWAY_GEHIS                  |    IX3 |   MOPB2TSMSV-05 |
 
ce que je veux en sortie c'est: ( Ligne ASPAWAY avec les trois serveurs )
 
| AGF                            |    MJ0 |   MOPB4TSMSV-01 |
| AGS                            |    FA3 |   MOPB4TSMSV-05 |
| AIR_LIQUIDE                    |    L02 |   MOPB2TSMSV-01 |
| ALC_EVILOG                     |    TY3 |   MOPB2TSMSV-03 |
| ALC_INFOR                      |    A39 |   MOPB2TSMSV-03 |
| ALC_IPNERGIE                   |    GE1 |   MOPB2TSMSV-03 |
| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| ARKEMA                         |    RK0 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 | MOPB4TSMSV-05 |   MOPB2TSMSV-03 |
| ASPAWAY_GEHIS                  |    IX3 |   MOPB2TSMSV-05 |
 
 
voici mon code :
 
        ######################
        # Domain_Name is not only one per line
        # Format to Description | Domain_Name | TSM_Server1 | TSM_Server2 ...
        ######################
        rm -f $Format2 2>&-
        rm -f $Format3 2>&-
 #############
 # on lit le fichier de départ ligne par ligne
 #############
        cat $TrigramClient | while read Line
        do
                Descri=`echo $Line | cut -d"|" -f2`
                Domain=`echo $Line | cut -d"|" -f3`
                Server=`echo $Line | cut -d"|" -f4`
  #############
  # on cherche dans le fichier 2 s'il y a une occurence
  #############
                Resu=`cat $Format2 | grep $Domain`
                if [ ${#Resu} = 0 ]
                then
   #############
   # si pas d'occurence on écrit la ligne dans le fichier2
   #############
                        print "$Line" >> $Format2
                else
   #############
   # sinon on récupère le nom du serveur TSM dans le fichier2
   # pour le comparer avec le nom du serveur dans le fichier1
   # Si c'est le même on écrit rien dans le fichier2
   #############
                        Resu2=`cat $Format2 | grep $Domain | cut -d"|" -f4`
                        if [ $Resu2 != $Server ]
                        then
   #############
    # La je veux Soit ajouter le nouveau serveur en fin de ligne du fichier2
    # Soit supprimer la ligne du fichier2 et la remplacer avec ligne du fichier1
    # + le nom du serveur déjà répertorié dans le fichier2
    #############

    sed "s/$Ligne/$Ligne $Resu2 |/g $Format2
 
   
                                sleep 15
 
                        fi
                fi
        done
 
Mais a que j'y arrive pas ! Alors merci pour votre aide ou solution différente...

Reply

Marsh Posté le 08-02-2007 à 08:54:19   

Reply

Marsh Posté le 08-02-2007 à 11:42:03    

Fred_l a écrit :

Bonjour, j'ai un problème avec sed.
 
voilà ce que je veux faire:
 
fichier1 contient:
 
| AGF                            |    MJ0 |   MOPB4TSMSV-01 |
| AGF                            |    MJ0 |   MOPB4TSMSV-01 |
| AGS                            |    FA3 |   MOPB4TSMSV-05 |
| AIR_LIQUIDE                    |    L02 |   MOPB2TSMSV-01 |
| ALC_EVILOG                     |    TY3 |   MOPB2TSMSV-03 |
| ALC_INFOR                      |    A39 |   MOPB2TSMSV-03 |
| ALC_IPNERGIE                   |    GE1 |   MOPB2TSMSV-03 |
| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| ARKEMA                         |    RK0 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-03 |

| ASPAWAY_GEHIS                  |    IX3 |   MOPB2TSMSV-05 |
 
ce que je veux en sortie c'est: ( Ligne ASPAWAY avec les trois serveurs )
 
| AGF                            |    MJ0 |   MOPB4TSMSV-01 |
| AGS                            |    FA3 |   MOPB4TSMSV-05 |
| AIR_LIQUIDE                    |    L02 |   MOPB2TSMSV-01 |
| ALC_EVILOG                     |    TY3 |   MOPB2TSMSV-03 |
| ALC_INFOR                      |    A39 |   MOPB2TSMSV-03 |
| ALC_IPNERGIE                   |    GE1 |   MOPB2TSMSV-03 |
| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| ARKEMA                         |    RK0 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 | MOPB4TSMSV-05 |   MOPB2TSMSV-03 |
| ASPAWAY_GEHIS                  |    IX3 |   MOPB2TSMSV-05 |
 
 
voici mon code :
 
        ######################
        # Domain_Name is not only one per line
        # Format to Description | Domain_Name | TSM_Server1 | TSM_Server2 ...
        ######################
        rm -f $Format2 2>&-
        rm -f $Format3 2>&-
 #############
 # on lit le fichier de départ ligne par ligne
 #############
        cat $TrigramClient | while read Line
        do
                Descri=`echo $Line | cut -d"|" -f2`
                Domain=`echo $Line | cut -d"|" -f3`
                Server=`echo $Line | cut -d"|" -f4`
  #############
  # on cherche dans le fichier 2 s'il y a une occurence
  #############
                Resu=`cat $Format2 | grep $Domain`
                if [ ${#Resu} = 0 ]
                then
   #############
   # si pas d'occurence on écrit la ligne dans le fichier2
   #############
                        print "$Line" >> $Format2
                else
   #############
   # sinon on récupère le nom du serveur TSM dans le fichier2
   # pour le comparer avec le nom du serveur dans le fichier1
   # Si c'est le même on écrit rien dans le fichier2
   #############
                        Resu2=`cat $Format2 | grep $Domain | cut -d"|" -f4`
                        if [ $Resu2 != $Server ]
                        then
   #############
    # La je veux Soit ajouter le nouveau serveur en fin de ligne du fichier2
    # Soit supprimer la ligne du fichier2 et la remplacer avec ligne du fichier1
    # + le nom du serveur déjà répertorié dans le fichier2
    #############

    sed "s/$Ligne/$Ligne $Resu2 |/g $Format2
 
   
                                sleep 15
 
                        fi
                fi
        done
 
Mais a que j'y arrive pas ! Alors merci pour votre aide ou solution différente...


 
Bon, les remarques de bases: cat ... |while read Line c'est bien pensé. Le seul soucis, c'est que si tu modifies une variable dans le pipe, elle est perdue en fin de done. Bon là t'es pas concerné mais faudra y penser si un jour ça t'arrive. On peut faire différemment de cette façon

exec 3<fichier
while read Line 0<&3
do
    ...
done


Pas de pipe donc pas de perte de variable.
 
Ensuite, tester si "Resu" (le résultat du "grep" ) = 0 c'est pas bon. Le grep te renvoie une ligne ou pas, donc tu testes si "Resu" est vide ou pas => "test -n" ou "test -z"
Ou alors tu testes si le grep réussi ou pas => if cat Format2 |grep $Domain 1>/dev/null ou plus simplement "if grep $Domain Format2 1>/dev/null"
 
Maintenant, j'ai pas examiné en détail ton algo (probablement parce qu'il y avait trop de commentaires), mais ta condition pour dire "on est sur la même ligne" c'est dire "est-ce que je trouve $Domain dans Format2" je trouve ça lourd => tu examines tout un fichier avec "grep" alors que seule la dernière ligne t'intéresse => tu aurais pu faire mieux avec "tail". Mais de toute façon je trouve ton truc trop fouillis. Pourquoi, quand tu es sur la ligne contenant "ASPAWAY", ne pas mémoriser ce fait et tant que t'es sur la même ligne, tu concatènes les autres champs puis, dès que t'as changé de ligne, tu écris la précédente ligne concaténée ?
Je verrais bien un truc de ce style
 

#!/bin/sh
cat fichier1 |while read Line        # Ou bien ma boucle à base de "exec"
do
    # Découpage de la ligne
    Descri=`echo $Line | cut -d"|" -f2`
    Domain=`echo $Line | cut -d"|" -f3`
    Server=`echo $Line | cut -d"|" -f4`
 
    # Si on n'est pas sur "ASPAWAY"
    if test "$Descri" != "ASPAWAY"
    then
        # Si on a une concaténation issue des lignes précédentes
        if test -n "$concat"
        then
              # On écrit la concaténation et RAZ
              echo $concat
              unset concat
        fi
 
        # La ligne courante n'est pas ASPAWAY - On l'écrit telle quelle
        echo "$Line"
    else
        # Si on est sur le premier ASPAWAY (chaine concat vide) on l'initialise
        test -z "$concat" && concat="| $Descri | $Domain"
 
        # On concatène le serveur
        concat="$concat | $Server"
    fi
done >fichier2


Message édité par Sve@r le 08-02-2007 à 18:51:06

---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 08-02-2007 à 20:26:25    

Tu peux essayer en Perl :


#!/usr/bin/perl
 
use strict;
use warnings;
 
my %descriptions;
while (<> ) {
  my (undef, $desc, $dom, $serv) = split(/[ |]+/, $_);
  $descriptions{$desc}->{$dom}->{$serv} = 1;
}
 
for my $desc (sort keys %descriptions) {
  my $hashref = $descriptions{$desc};
  for my $dom (sort keys %{ $hashref }) {
    print "| $desc | $dom | ", join(' | ', keys(%{ $hashref->{$dom} })), " |\n";
  }
}


 
C'est sans doute pas optimal, mais ça a l'avantage de ne parcourir le fichier d'entrée qu'une seule fois. Les descriptions sont données dans l'ordre alphabétiques, les domaines aussi, et les serveurs dans un ordre arbitraire.
 

$ ./monprog.pl fichier_entree.txt > fichier_sortie.txt

Reply

Marsh Posté le 08-02-2007 à 21:21:10    

Sinon avec awk (si tu as sed, tu doit avoir awk). Encore une fois, le fichier n'est parcouru qu'une seule fois et un seul processus est lancé, mais ça suppose que les descriptions et les serveurs soient dans l'ordre dans le fichier d'entrée.
 
Par exemple, cette entrée fonctionnera :


| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| ARKEMA                         |    RK0 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY_GEHIS                  |    IX3 |   MOPB2TSMSV-05 |


 
Mais celle-ci ne fonctionnera pas :


| AMS                            |    YM0 |   MOPB2TSMSV-05 |
| ARKEMA                         |    RK0 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY                        |    IX4 |   MOPB4TSMSV-05 |
| ASPAWAY                        |    IX3 |   MOPB2TSMSV-05 |
| ASPAWAY_GEHIS                  |    IX3 |   MOPB2TSMSV-05 |


 
Voici le script awk :


#!/usr/bin/awk -f
 
BEGIN {
  FS = "[ |]+"
  ORS = ""
}
 
{
  if (dd[$2, $3]) {
    if (!vus[$4]) {
      print $4, " | "
      vus[$4] = 1
    }
  } else {
    dd[$2, $3] = 1
    delete vus
    print "\n| ", $2, "      | ", $3, "      | ", $4, "      | "
    vus[$4] = 1
  }
}


 
Il commence par écrire un retour à la ligne, ce qui est un mini-défaut. Tu peux l'adapter.
 

$ ./script.awk entree.txt > sortie.txt


Message édité par frednoob le 08-02-2007 à 21:24:17
Reply

Marsh Posté le 08-02-2007 à 21:24:05    

frednoob a écrit :


C'est sans doute pas optimal, mais ça a l'avantage de ne parcourir le fichier d'entrée qu'une seule fois.


Mon script aussi ne lit le fichier d'entrée qu'une seule fois...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 08-02-2007 à 21:31:54    

Sve@r a écrit :

Mon script aussi ne lit le fichier d'entrée qu'une seule fois...


Mais le fichier de sortie est lu plusieurs fois. De plus, si l'écriture est bufferisée, peut-être que ça peut poser problème, sauf à s'assurer de vider le buffer après chaque ajout. Je ne suis pas sûr cela dit. Je préfère aussi utiliser un seul processus plutôt que d'en lancer plusieurs (cat, grep, etc.). D'ailleurs, tu peux améliorer

cat $Format2 | grep $Domain


en

grep $Domain $Format2


Ça fait toujours un processus de moins.
 
Pendant que j'y suis, voici une petite amélioration de mon script awk (utilise moins de mémoire) :


#!/usr/bin/awk -f
 
BEGIN {
  FS = "[ |]+"
  ORS = ""
}
 
{
  if (dd[$2, $3]) {
    if (!vus[$4]) {
      print $4, " | "
      vus[$4] = 1
    }
  } else {
    delete dd
    delete vus
    print "\n| ", $2, "      | ", $3, "      | ", $4, "      | "
    dd[$2, $3] = 1
    vus[$4] = 1
  }
}

Reply

Marsh Posté le 09-02-2007 à 07:26:11    

frednoob a écrit :

Mais le fichier de sortie est lu plusieurs fois. De plus, si l'écriture est bufferisée, peut-être que ça peut poser problème, sauf à s'assurer de vider le buffer après chaque ajout. Je ne suis pas sûr cela dit. Je préfère aussi utiliser un seul processus plutôt que d'en lancer plusieurs (cat, grep, etc.).


Tes remarques s'appliquent au script de Fred_L (premier post) et non au mien (deuxième post) - Va relire les posts du début !!!
Mon script ne lit qu'une seule fois un seul fichier qui est le fichier d'entrée
 

frednoob a écrit :

D'ailleurs, tu peux améliorer

cat $Format2 | grep $Domain


en

grep $Domain $Format2


Ça fait toujours un processus de moins.


Ca aussi je l'ai dit dans mon premier post !!!


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Marsh Posté le 09-02-2007 à 12:40:43    

Ah oui, désolé Sve@r. Par contre, ton script ne fonctionne que pour les lignes ASPAWAY, et on ne sait pas si ce cas particulier suffit à résoudre le problème, ou si d'autres lignes peuvent avoir besoin d'être regroupées (ce que j'ai supposé dans mes exemples).

Reply

Marsh Posté le 09-02-2007 à 15:58:38    

frednoob a écrit :

Ah oui, désolé Sve@r. Par contre, ton script ne fonctionne que pour les lignes ASPAWAY, et on ne sait pas si ce cas particulier suffit à résoudre le problème, ou si d'autres lignes peuvent avoir besoin d'être regroupées (ce que j'ai supposé dans mes exemples).


Exact - Il avait parlé de "ASPAWAY" donc je n'ai considéré que ASPAWAY...
 
Si la contrainte devient "reconnaitre plusieurs mots", on reverra le script...


---------------
Vous ne pouvez pas apporter la prospérité au pauvre en la retirant au riche.
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed