IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Shell et commandes GNU Discussion :

Edition de fichier volumineux


Sujet :

Shell et commandes GNU

  1. #1
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut Edition de fichier volumineux
    Bonjour,

    Je vous expose mon problème :

    je dispose de plusieurs fichiers (actuellement 33).
    Je cherche à détecter les lignes en anomalies pour les corriger.
    Toutes les lignes doivent faire 600 caractères de long et commencer par 3 lettres majuscule + $ (ex: ABC$ ou FYE$ ou FFF$)
    La commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep  -vn  '^\w{3}\$*{596}'  fichier
    me permet de détecter ces lignes.
    Elles m'affichent sous cette forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    nom_du_fichier:numero_de_ligne_en_erreur:contenu_de_la_ligne_en_erreur
    Je dispose d'un fichier avec une ligne en erreur, il fait 3,30 Go et contient 5 497 219 de lignes.
    Au total mes 33 fichiers font 37,24 Go pour 81 051 621 de lignes.

    Je souhaiterai pouvoir "réparer" ces fichiers, c'est à dire que la ligne en erreur soit à la suite de la ligne qui la précède.
    J'ai cherché pour supprimer les sauts de lignes qui ne seraient pas à la position 601, mais je ne m'en sorts pas

    Des idées ?

  2. #2
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Bonjour,

    Ok, on sait que tes lignes doivent faire 600 caractères mais quels types de caractères, 1 octet ou variable (par exemple le é latin en utf8 est sur 2 octets) ?

    Ensuite, comment on répare une ligne automatiquement ?

    Après, coté idée, tu as des outils comme awk, sed, perl,...
    Cordialement.

  3. #3
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Ca viens d'un mainframe (zOs) avec une table de caractère en EBCDIC, c'est donc 1 caractère pour 1 octet.

    Actuellement j'ai ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ligne_en_erreur=`egrep -nv '^\w{3}\$*{596}' $fichier | cut -d':' -f1`
    ligne_precedente=$(($ligne_en_erreur - 1))
    ligne_reparee=`sed -n ${ligne_precedente},${ligne_en_erreur}p $fichier | tr "\n" "\ "`
    Le problème c'est que je dois remettre tout ça dans le fichier et à la bonne ligne.

    Les lignes ont se format :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    DEB$C005$E$2$    $    $0000000000$0999999999$ACTIVE $2017-01-06$2016-09-02$
    DET$C005$D$0005497216$C$721
    FIN$C005$F$000000005497218$
    Chaque ligne à le caractère $ comme séparateur de champ.
    Le 1er champ sert à définir le type de ligne
    Le 5ème champ représente le numéro de la ligne.

    On pourrait donc imaginer de recopier la ligne_reparee à la fin puis de trier le fichier par ordre croissant sur le 5ème champ, mais je ne sais simplement pas faire.

  4. #4
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Euh... c'est pas complètement clair pour moi...

    L'idéal serait que tu nous montres ce que tu appelles la ligne en erreur, ainsi qu'un peu de contexte (quelques précédentes et suivantes), par exemple de la manière suivante:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep  -vn -C2  '^\w{3}\$*{596}'  fichier # 2 lignes avant et 2 lignes après
    et également, afin qu'on voie la nature des fins de ligne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep  -vn -C2  '^\w{3}\$*{596}'  fichier | od -c
    Puis que tu nous montres comment tu voudrais voir le bloc corrigé.

    Citation Envoyé par Bragu Demon Voir le message
    Je souhaiterai pouvoir "réparer" ces fichiers, c'est à dire que la ligne en erreur soit à la suite de la ligne qui la précède.
    J'ai cherché pour supprimer les sauts de lignes qui ne seraient pas à la position 601, mais je ne m'en sorts pas
    Citation Envoyé par Bragu Demon Voir le message
    Actuellement j'ai ça :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    ligne_en_erreur=`egrep -nv '^\w{3}\$*{596}' $fichier | cut -d':' -f1`
    ligne_precedente=$(($ligne_en_erreur - 1))
    ligne_reparee=`sed -n ${ligne_precedente},${ligne_en_erreur}p $fichier | tr "\n" "\ "`

    D'après ce que tu dis, j'ai l'impression que certaines lignes sont "coupées", avec un CR ou un LF en trop, et qu'il faut raccorder les bouts.

    Mais, si c'est bien ça, alors tu devrais avoir DEUX lignes consécutives avec moins de 600 caractères, non?

    Et, en conséquence, il ne faut pas raccorder la première ligne en erreur avec la précédente, mais plutôt raccorder la deuxième ligne en erreur avec la précédente, non?

    Car si on met la première ligne en erreur à la suite de sa précédente, alors celle-ci fera plus de 600 caractères, non?

    PS: il est clair qu'il vaut mieux utiliser un bon script, mais je voudrais préciser que "emacs" est un éditeur assez efficace pour éditer à la main (ou avec des macros emacs) de tels gros fichiers...

  5. #5
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Citation Envoyé par jack-ft Voir le message
    Euh... c'est pas complètement clair pour moi...


    egrep -vn -C2 '^\w{3}\$*{596}' fichier # 2 lignes avant et 2 lignes après
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    1493889-SUC$C005$D$0001493888$S$30256402
    1493890-PDR$C005$D$0001493889$C$30256402
    1493891:                                
    1493892-TRA$C005$D$0001493890$C$30256402
    1493893-UGD$C005$D$0001493891$C$30256402
    Voici comment sont constituées les lignes :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    DEB$C005$E$2$    $    $0000000000$0999999999$ACTIVE $
    PDR$C005$D$0000000001$M$2014
    ...
    DET$C005$D$0005497216$C$72110
    FIN$C005$F$000000005497218$
    colonnes 1 à 3 : identification du type d'enregistrement (DEB -> Début, FIN -> Fin)
    colonnes 5 à 8 : code institutionnel
    colonnes 10 : type d'information (E -> Entête, D -> Data, F -> Fin)
    colonnes 12 -> "$" : numéro d'enregistrement
    chaque enregistrement fait 600 caractères de long, et donc 600 octets de long (c'est extrait d'un DB2 Z/OS)

    On voit ici que le 4ème champ (et pas le 5ème comme je le disais plus haut) contient le numéro de l'enregistrement.
    La ligne 1493889 est parfaite. On observe un décalage dans la numérotation, dû au fait que la 1ère ligne (DEB$) n'est pas numérotée.
    La ligne de fin (FIN$) contient elle le nombre de ligne dans le fichier (ligne DEB$ comprise).
    Ainsi wc -l fichier retourne 5497219 alors que la bannière de fin (FIN$) dit que l'on doit en avoir 54972198.




    nature des fins de ligne (j'ai triché j'ai mis qu'une ligne avant et après) :
    egrep -vn -C1 '^\w{3}\$*{596}' fichier | od -c
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
     
    0000000   1   4   9   3   8   9   0   -   P   D   R   $   C   0   0   5
    0000020   $   D   $   0   0   0   1   4   9   3   8   8   9   $   C   $
    0000040   3   0   2   5   6   4   0   2   5
    0000060                   $   0   3   0   2   5   6   4   0   2   5   $
    0000100   0   1   0   1   0   8   1   6   4   8   $   0   0   0   0   0
    0000120   0   0   0   0   0   $   0   0   0   0   0   0   2   6   1   2
    0000140   6   7   0   5   4   $   0   0   6   6   3   6   3   4   7   4
    0000160   $   0   0   0   0   0   $   0   0   0   0   0   0   0   0   0
    0000200   0   0   0   0   0   0   $   0   0   0   0   0   0   0   0   0
    *
    0000240   0   0   0   0   0   0   $   0   0   0   $   0   0   0   $   0
    0000260   0   0   $   0   0   0   $   0   0   0   0   0   $
    0000300                               $
    0000320                                                   $
    0000340       $   0   0   0   0   0   0   0   0   0   0   0   0   0   0
    0000360   $
    0000400
    *
    0000440                                                       $       $
    0000460
    0000500   $   2   0   0   1   -   0   2   -   1   2   $   2   0   1   3
    0000520   -   0   3   -   0   1   $   0   9   6   $   0   1   $   2   0
    0000540   0   $   N   $   0   0   0   0   0   0   0   0   0   3   $   2
    0000560   0   1   1   -   1   1   -   0   1   $   2   0   1   6   -   1
    0000600   2   -   0   1   $   M   I   G   R   A   T   I   O   N
    0000620                                       $   P   N   D   S   M   B
    0000640   P   1                                                   $
    0000660       $   C   L   I   N   I   Q   U   E       S   A   I   N   T
    0000700   -   S   A   U   V   E   U   R      \n   1   4   9   3   8   9
    0000720   1   :
    0000740
    *
    0001020                                                           $   S
    0001040   I   R   N   $   4   1   3   9   6   8   4   1   3
    0001060                                   $
    0001100
    *
    0001140                                  \n   1   4   9   3   8   9   2
    0001160   -   T   R   A   $   C   0   0   5   $   D   $   0   0   0   1
    0001200   4   9   3   8   9   0   $   C   $   3   0   2   5   6   4   0
    0001220   2   5                                               $   0   3
    0001240   0   2   5   6   4   0   2   5   $   0   1   0   1   0   8   1
    0001260   6   4   8   $   0   0   0   0   0   0   0   0   0   0   $   0
    0001300   0   0   0   0   0   2   6   1   2   6   7   0   5   4   $   0
    0001320   0   6   6   3   6   3   4   7   4   $   0   0   0   0   5   $
    0001340   0   0   0   0   0   0   0   0   0   0   0   0   0   0   0   $
    *
    0001420   0   0   4   $   0   0   1   $   0   0   0   $   0   0   0   $
    0001440   0   0   0   0   0   $
    0001460   $
    0001500                       $                   $   0   0   0   0   0
    0001520   0   0   0   0   0   0   0   0   0   $   C   $   0   1   3   $
    0001540   C   $   0   1   3   $               $               $   0   0
    0001560   0   3   0   3   7   3   6   6   $   0   0   4   $   0   1   6
    0001600   2   4   0   0   $   0   0   0   0   0   0   0   $   0   1   6
    0001620   2   4   0   0   $   0   0   0   0   0   0   0   $   2   0   1
    0001640   6   -   1   2   -   0   1   $
    0001660           $   P   N   D   S   M   B   P   1
    0001700                               $
    0001720                                                   $
    0001740
    *
    0002300                                      \n
    0002312


    Citation Envoyé par jack-ft Voir le message
    D'après ce que tu dis, j'ai l'impression que certaines lignes sont "coupées", avec un CR ou un LF en trop, et qu'il faut raccorder les bouts.

    Mais, si c'est bien ça, alors tu devrais avoir DEUX lignes consécutives avec moins de 600 caractères, non?
    C'est presque vrai, dans mes contrôles je dois m'assurer que chaque commence par 3 lettres + "$" ET soit de 600 de long, d'ou mon egrep :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep -vn '^\w{3}\$*{596}'  fichier
    le -v permet de récupérer ce qui NE CORRESPOND PAS à l'expression qui suis, et le -n pour récupérer le numéro de la ligne.
    Dans ce cas là, il faut bien recoller la ligne récupérée avec la précédente.

    Par contre avec un test sur uniquement la longueur de la ligne il faut recoller les 2 lignes en erreurs, la deuxième ligne en erreur avec la précédente, comme tu le dis.
    Cette commande ne fonctionne pas, elle ne me rencoi rien du tout à la console ... :-(
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep -vn '^*{600}' fichier
    Citation Envoyé par jack-ft Voir le message
    PS: il est clair qu'il vaut mieux utiliser un bon script, mais je voudrais préciser que "emacs" est un éditeur assez efficace pour éditer à la main (ou avec des macros emacs) de tels gros fichiers...
    J'ai bien l'intention de mettre tout ça dans un script.
    Concernant emacs, je ne connais mais que de nom et je suis parfaitement incapable d'en faire quoique se soit ( pour l'instant :-) )

    Actuellement :
    Je sais identifier les lignes que je doit concaténer
    Je sais concaténer les 2 lignes qui m'intéresse

    A faire :
    concaténer mon fichier avec ma ligne réparée (la mettre bêtement à la fin) --> CAT va m'aider
    Supprimer les lignes utilisées pour effectuer la réparation --> sed -e '${ligne_precedente}d;${ligne_en_erreur}d' fichier
    Faire un sort croissant sur le champ 4 du fichier (dont le séparateur est le $ )

  6. #6
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Actuellement :



    Il ne me manque "que" :
    Faire un sort croissant sur le champ 4 du fichier (dont le séparateur est le $ ) :
    [EDIT]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    cat fichier | sort -t$ -k 4n,4n > NEW_fichier
    [/EDIT]

    Je vous tiens au courant ^^

  7. #7
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    J'ai toujours pas trop compris, mais une chose est sure: la regex du egrep n'est pas bonne ou du moins, elle ne fait ce que tu penses car il suffit que ta ligne commence par 3 caractères de la classe \w pour que la regex la considère comme correcte et donc ne te l'affichera pas ( a cause du -v ):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    $ echo 'xxx' | egrep -nv '^\w{3}\$*{596}'
    $ echo 'xx' | egrep -nv '^\w{3}\$*{596}'
    1:xx
    $ echo '   ' | egrep -nv '^\w{3}\$*{596}'
    1:
    La bonne regex serait plutôt:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep -nv '^\w{3}\$.{596}$'
    De plus, pas besoin de faire tout ce que tu fais (egrep, sed, tr, sed, sort)... un simple sed suffirait mais avant, confirme que malgré l'erreur de ta regex, ton raisonnement reste valide et explique nous un peu comment tu concatènes les 2 lignes (en rajoutant un espace à la place de '\n' ???)
    Cordialement.

  8. #8
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Voici un exemple qui peut t'aider en une seule ligne sed:

    Prenons un fichier dont la longueur d'une ligne est de 51 octets:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    $ cat -n /tmp/fic 
         1	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         2	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         3	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         4	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         5	A B C D E F G
         6	H I J K L M N O P Q R S T U V W X Y Z
         7	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         8	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         9	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
        10	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
        11	A B C D
        12	E F G H I J K L M N O P Q R S T U V W X Y Z
    Comme on peut le voir, les couples de lignes (5,6) et (11,12) devrait normalement ne former chacun qu'une seule ligne, il faudrait donc qu'on trouve ces couples et qu'on les concatène pour que le fichier soit valide.
    On pourrait très bien reprendre ta méthode, qui récupére ici la ligne courante et la ligne suivante, on les concaténe, ....
    Mais autant le faire directement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $ sed '/^.\{51\}$/b;N;s/\n/ /' /tmp/fic | cat -n
         1	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         2	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         3	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         4	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         5	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         6	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         7	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         8	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
         9	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
        10	A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
    Bon, ici, le code sed est simple mais il ne réctifie pas le tir si la ligne est tronquée sur 3 ligne ou plus au lieu de 2.
    Cordialement.

  9. #9
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Bon, ici, le code sed est simple mais il ne rectifie pas le tir si la ligne est tronquée sur 3 ligne ou plus au lieu de 2.
    Peut-être en relançant la même commande en boucle tant qu'elle produit un résultat différent... ()

  10. #10
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    Citation Envoyé par Bragu Demon Voir le message
    C'est presque vrai, dans mes contrôles je dois m'assurer que chaque commence par 3 lettres + "$" ET soit de 600 de long, d'ou mon egrep :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep -vn '^\w{3}\$*{596}'  fichier
    Supposons que ce soit egrep -vn '^\w{3}\$.{596}' fichier comme corrigé par disedorgue...


    le -v permet de récupérer ce qui NE CORRESPOND PAS à l'expression qui suis, et le -n pour récupérer le numéro de la ligne.
    oui, je connais un peu "grep"...

    Dans ce cas là, il faut bien recoller la ligne récupérée avec la précédente.
    Oui, mais là, non... ou alors je persiste à ne pas comprendre!

    Tu décèles la première ligne mauvaise. Elle est consécutive à une précédente qui est forcément bonne, puisque la première mauvaise est, comment dire, la première à être mauvaise...

    Du coup, si tu colles la mauvaise ligne à la fin de la précédente, celle-ci verra sa longueur augmenter et ne sera plus bonne, non?

    Par contre avec un test sur uniquement la longueur de la ligne il faut recoller les 2 lignes en erreurs, la deuxième ligne en erreur avec la précédente, comme tu le dis.
    Hum...

    Cette commande ne fonctionne pas, elle ne me rencoi rien du tout à la console ... :-(
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    egrep -vn '^*{600}' fichier
    Normal... (voir disedorgue)

  11. #11
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Citation Envoyé par jack-ft Voir le message
    Peut-être en relançant la même commande en boucle tant qu'elle produit un résultat différent... ()
    Mouais, il est vrai que j'aurai pu rajouter la boucle, j'étais pas à 6 caractère près (3 à chaque extrème) mais tant pis, je laisse la rectification à qui veut faire l'exercice.
    Cordialement.

  12. #12
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    $ sed '/^.\{51\}$/b;N;s/\n/ /' /tmp/fic | cat -n


    C'est trop beau

    Par contre ça ne fonctionne pas :-(

    J'ai explosé mon fichier et je me retrouve avec 132 lignes de décalage

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    $ sed -n 1493889,1493892p fichier_repare
    $ sed -n 1493889,1493892p fichier_OK
    0000001   DEB$C005$E$2$    $
    1493889   DDN$C005$D$0001493888$
    1493890   DRT$C005$D$0001493889$
    1493891   DET$C005$D$0001493890$
    1493892   TRA$C005$D$0001493891$
    1835273   FIN$C005$F$000000001835273$ 
     
     
    sed -n 1493889,1493892p fichier_KO
    0000001   DEB$C005$E$2$    $
    1493889   DDN$C005$D$0001493927$
    1493890   DRT$C005$D$0001493928$
    1493891   DET$C005$D$0001493929$
    1493892   TRA$C005$D$0001493930$
    5497086   FIN$C005$F$000000005497218$ 
     
     
    sed -n 1493889,1493892p fichier_origine
    0000001   DEB$C005$E$2$    $
    1493889   SUC$C005$D$0001493888$
    1493890   PDR$C005$D$0001493889$
    1493891                         
    1493892   TRA$C005$D$0001493890$
    5497219   FIN$C005$F$000000005497218$
    J'ai rajouté le numéro des lignes, histoire d'y voir plus clair.
    Chaque ligne (toutes) contient 600 caractères de long ET doit commencer par 3 lettres puis 1 $

    egrep -vn '^\w{3}\$*{596}' fichier me permet d'identifier le fichier en erreur (c'est certainement perfectible) :

    Le séparateur est donc le $, le 4ème champ représente le numéro de l'enregistrement.

    Alors on peut voir plusieurs choses :
    Dans le fichier OK :
    Il y a un décalage de 1, ça provient du fait que la ligne 1 ne soit pas numérotée.
    La ligne de fin contient le nombre d'enregistrement total du fichier (ligne de début comprise)

    Dans le le fichier KO :
    On vois que j'ai un décalage de 132 ligne

    Dans le fichier d'origine :
    On voit un décalage de 1 ligne

    Je veux bien un coup de main pour arriver à supprimer les retours chariots qui ne sont pas à la position 601.

  13. #13
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Bonjour,

    sur cette solution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    sed '/^.\{600\}$/b;N;s/\n/ /' /tmp/fic
    J'ai pu constater que sur un fichier test de 18 Mo, la correction est faite, alors que sur un fichier de 24 Mo j'observe le même phénomène, cad un fichier "réparé" qui au final contient plusieurs lignes en erreur

  14. #14
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Alors, petit rappel, ton grep n'est pas bon (voir les précédents posts).

    En ce qui concerne le sed, celui-ci ne fait que:

    /^.\{600\}$/b : si ligne fait exactement 600 caractères (retour à la ligne exclu) alors on saute à la fin du script sed, ce qui permet de passer à la ligne suivante.
    N : rajouter un retour à la ligne à la fin du buffer, lire la ligne suivante et la mettre à la fin du buffer.
    s/\n/ / : remplacer le premier retour à la ligne par un espace.

    Ce qu'il ne prend pas en compte, c'est le cas que j'appellerais (), c'est si la ligne est coupé en plus de 2 lignes consécutives, alors de nouvelles erreurs se produiront, comme par exemple le cas suivant:
    1 ligne ok
    2 ligne coupé
    2 suite 1 ligne coupé
    2 suite 2 ligne coupé
    3 ligne ok

    Ce que le sed fera:
    1 ligne ok
    2 ligne coupé 2 suite 1 ligne coupé
    2 suite 2 ligne coupé 3 ligne ok

    Donc, comme tu peux le voir, au final, tu auras bien 3 lignes, mais 2 qui seront fausses, car la ligne 2 sera toujours incomplète et la ligne 3 aura récupéré la fin de la ligne 2.

    Pour résoudre ce cas , jack-ft à décrit la solution, qu'il faudrait implémenter directement dans le sed.

    Mais est-ce bien ce cas que tu rencontres ?
    Cordialement.

  15. #15
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Alors, petit rappel, ton grep n'est pas bon (voir les précédents posts).
    Concernant mon grep, il y a une petite chose que je ne comprends pas :

    Si je l'exécute sur mon fichier :
    • j'obtiens le numéro de ligne (comme indiqué dans mon premier post)
    • Si j'ouvre mon fichier (j'utilise glogg) et que je vais sur cette même ligne (au passage je n'arrive pas à aller directement à une ligne donnée, comme par ctrl+G dans sublime text. La doc de glogg mentionne ctrl+w mais ça ferme le fichier ) je constate bien mon erreur.
    • Si je compare le contenu de ma dernière ligne (qui m'indique le nombre d'enregistrement attendu) avec le nombre d'enregistrement total, j'ai un différentiel de 1, il n'y a donc qu'une ligne en erreur.



    En ce qui concerne le sed, celui-ci ne fait que:

    /^.\{600\}$/b : si ligne fait exactement 600 caractères (retour à la ligne exclu) alors on saute à la fin du script sed, ce qui permet de passer à la ligne suivante.
    N : rajouter un retour à la ligne à la fin du buffer, lire la ligne suivante et la mettre à la fin du buffer.
    s/\n/ / : remplacer le premier retour à la ligne par un espace.
    Si j'exécute celui-ci (le bon), toutes les lignes de mon fichier s'affiche (je ne l'es ai pas comptées, il y en a 5 400 000 et des briquettes)

    Bref le mauvais grep (et je veux bien vous croire sur ce point, je novice en linux et encore plus en sed/grep/awk et autre) me donne le "bon" résultat, tel qu'attendu et exploitable, alors que le bon grep non ...... :comprendpas:

    Je pense que si on pouvais commencer par là ça serait un grand pas pour moi

    En tout cas merci pour vos réponses.

  16. #16
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Essaye le bout de perl unligne suivant sur ton fichier d'origine, pour voir ce que cela donne, après on verra:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl -ne '$nr++ while m/\G./gc ; $hr{$nr}++;$nr=0 ;END{foreach $a (keys %hr) { print "$hr{$a} lignes de longueur $a\n" }}' fichier_origine
    Celui-ci va nous donner le nombre de ligne qu'il y a pour chaque taille de ligne trouvée.
    Cordialement.

  17. #17
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Voici le résultat :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    1 lignes de longueur 449
    5497217 lignes de longueur 600
    1 lignes de longueur 150
    Ce qui me rassure, à force j'avais un doute

  18. #18
    Expert éminent sénior Avatar de disedorgue
    Homme Profil pro
    Ingénieur intégration
    Inscrit en
    Décembre 2012
    Messages
    4 278
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur intégration
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Décembre 2012
    Messages : 4 278
    Points : 12 726
    Points
    12 726
    Par défaut
    Ok, mais là, je ne comprend pas pourquoi le sed ne fonctionnerai pas (sauf si les 2 lignes ne sont pas continu ou alors 600 est trop grand pour ton sed).

    Un petit perl qui te donnera les n° de ligne dont la taille est inférieur à 600:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl -ne '$nr++ while m/\G./gc ; print "$.\n" if $nr < 600; $nr=0'
    Comme ça, on pourra vérifier que les lignes se suivent (dans un premier temps).
    Cordialement.

  19. #19
    Expert confirmé
    Homme Profil pro
    Développeur informatique en retraite
    Inscrit en
    Avril 2008
    Messages
    2 101
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Côtes d'Armor (Bretagne)

    Informations professionnelles :
    Activité : Développeur informatique en retraite

    Informations forums :
    Inscription : Avril 2008
    Messages : 2 101
    Points : 5 849
    Points
    5 849
    Par défaut
    [ORTOGRAF]
    Citation Envoyé par disedorgue Voir le message
    Ok, mais là, je ne comprends pas pourquoi le sed ne fonctionnerait pas (sauf si les 2 lignes ne sont pas contiguës ou alors 600 est trop grand pour ton sed).

    Un petit perl qui te donnera les n° de ligne dont la taille est inférieure à 600:
    [/ORTOGRAF]

  20. #20
    Membre régulier Avatar de Bragu Demon
    Homme Profil pro
    Intégrateur d'Explopitation
    Inscrit en
    Juin 2013
    Messages
    125
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Intégrateur d'Explopitation
    Secteur : Service public

    Informations forums :
    Inscription : Juin 2013
    Messages : 125
    Points : 117
    Points
    117
    Par défaut
    Citation Envoyé par disedorgue Voir le message
    Un petit perl qui te donnera les n° de ligne dont la taille est inférieur à 600:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    perl -ne '$nr++ while m/\G./gc ; print "$.\n" if $nr < 600; $nr=0'
    Comme ça, on pourra vérifier que les lignes se suivent (dans un premier temps).
    Ça me fait bien plaisir ce petit perl, dont voici le résultat
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    $ perl -ne '$nr++ while m/\G./gc ; print "$.\n" if $nr < 600; $nr=0' fichier
    1493890
    1493891
    par contre le perl ne me rend pas la main :-(

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Transfert de fichiers volumineux par le net
    Par K-Kaï dans le forum Général Conception Web
    Réponses: 8
    Dernier message: 14/07/2008, 13h15
  2. [FTP] Editer des fichiers distants
    Par bigtof dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 17/08/2006, 00h28
  3. XP PRO SP2 detection de fichiers volumineux
    Par HOFER dans le forum Windows XP
    Réponses: 3
    Dernier message: 14/08/2006, 12h47
  4. [XML-JSP] Editer un fichier XML
    Par sempire dans le forum Format d'échange (XML, JSON...)
    Réponses: 1
    Dernier message: 24/08/2005, 22h24
  5. Chargement fichier volumineux
    Par kirsoul dans le forum Installation
    Réponses: 2
    Dernier message: 26/07/2005, 14h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo