Précédent   Forum des professionnels en informatique > Systèmes > Autres systèmes > Unix
Unix Forum d'entraide sur les systèmes Unix et dérivés (*BSD, AIX, etc.). Avant de poster ->F.A.Q BSD F.A.Q. Aix
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
Vieux 21/07/2009, 10h35   #1
Invité de passage
 
Inscription : juillet 2009
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 11
Points : 1
Points : 1
Par défaut SHELL insertion de caractere et saut de ligne

Reposté ailleurs :
http://www.developpez.net/forums/d78...e/#post4501971

Plop,

J'aurai besoin de vos lumière
j'ai pas trouvé grand chose sur le net pour ma problématique particulière alors je pose la question.

J'ai un fichier de 3mo composé d'une seule ligne...
ex (j'ai remplacé les espaces par des "_"):
"30004SCT_TARTENPION________________00003FONTEN"
et je dois rajouté des ";" à des emplacement fixes(au bout de 5 caractères j'insère ";" puis 20 caractères après ";" puis 5 caractères après ";" etc...) et au bout de 900 caractères je dois sauter à la ligne et recommencer l'insertion de ";".
Ce qui doit me donner un fichier composé de 3000 lignes ayant cette tête :
"30004;SCT_TARTENPION_________;_____;00003;FONTEN..."
"55204;BLABLABLAET BLABLABLA___;-003-;00003;FONTEN..."
J'ai pensé à sed ou awk mais je sais pas comment faire.
Voila merci de m'avoir lu.

Bye

Dernière modification par mangalor ; 21/07/2009 à 16h35. Motif: Reposté ailleurs
mangalor est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2009, 15h36   #2
Invité régulier
 
Inscription : septembre 2009
Messages : 6
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 6
Points : 6
Points : 6
Salut,
peut etre as tu trouvé une solution depuis le temps mais bon, j'ai crée un petit shell qui semble fonctionner .
Note: variables IN=<fichier a traiter> OUT=<fichier obtenu>


#!/bin/ksh

#Fonction qui met les separateurs dans le bloc de caractere

function fctsed {


res=$(echo $@ | sed "s/^\(.....\)\(....................\)\(.....\)/\1;\2;\3;/")


chaine=$(echo $res | grep ';' | awk -F';' '{print $NF}')
chaineok=$(echo $chaineok$res | grep ';' | awk -F';' '{for (i=1;i<NF;i++) printf $i";" }')

if [ -n "$chaine" ]
then
fctsed $chaine
fi

}

#Variables

IN=trait.txt
OUT=res.txt
lenght_ligne=889
lenght_fic=$(cat $IN | wc -c)
i=1

#Boucle principale qui cree chaque ligne du nouveau fichier

while(( i < $lenght_fic ))
do

(( j = i + $lenght_ligne ))
chaine=""
chaineok=""
fctsed $(cat $IN | cut -c${i}-${j} )
echo $chaineok >> $OUT
(( i = i + $lenght_ligne + 1 ))

done

Dernière modification par sinamone ; 20/09/2009 à 15h43. Motif: suppression saut de ligne impromptu
sinamone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 20/09/2009, 18h30   #3
Invité régulier
 
Inscription : septembre 2009
Messages : 6
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 6
Points : 6
Points : 6
EN fait y a bien plus court !

#!/bin/ksh

#Variables
IN=trait.txt
OUT=res.txt
lenght_ligne=899
lenght_fic=$(cat $IN | wc -c)
i=1

#Boucle principale qui cree chaque ligne du nouveau fichier
while(( i < $lenght_fic ))
do

(( j = i + $lenght_ligne ))
cat $IN | cut -c${i}-${j}\
| sed "s/\(.\{5\}\)\(.\{20\}\)\(.\{5\}\)/\1;\2;\3;/g" >> $OUT
(( i = i + $lenght_ligne + 1 ))

done
sinamone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/09/2009, 15h24   #4
Invité de passage
 
Inscription : juillet 2009
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 11
Points : 1
Points : 1
Solution trouvé sur un fofo us(www.unix.com)

Merci à tous et comme ça pourrait être utile voici la solution finale
En perl la boucle lit le fichier entré en variable et insert les caractères ";" puis le fin de ligne à 900.
Une fois terminé on remplace par rien les 14 derniers caractères(qui commence par 0,1 ou 2) de chaque lignes et on balance ça dans un fichier "_traite", voilou.
Code :
1
2
3
4
5
6
7
perl -ne 'chomp;
    while(/(.)/g){
       $i++; print $1; $x=$i%900;
       if ($x == 0){print "\n"}
       elsif ($x==5 or $x==37 or $x==42 or $x==74 or $x==79 or $x==111 or $x==116 or $x==148 or $x==153 or $x==185 or $x==187 or $x==192 or $x==224 or $x==256 or $x==288 or $x==320 or $x==333 or $x==335 or $x==340 or $x==372 or $x==404 or $x==436 or $x==468 or $x==475 or $x==480 or $x==487 or $x==503 or $x==504 or $x==509 or $x==541 or $x==573 or $x==605 or $x==637 or $x==642 or $x==655 or $x==662 or $x==694 or $x==726 or $x==758 or $x==790 or $x==795 or $x==808 or $x==815 or $x==828 or $x==830 or $x==835 or $x==840 or $x==845 or $x==847 or $x==852 or $x==861 or $x==865 or $x==870 or $x==874 or $x==878 or $x==882){print ";"}
       }' $1 | sed -e 's/[0-2]             $//' > $1_traite
mangalor est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 22/09/2009, 21h26   #5
Modérateur
 
Avatar de ok.Idriss
 
Homme Idriss Neumann
Développeur en SSII et étudiant au CNAM Paris (ingénieur SI)
Inscription : février 2009
Messages : 1 705
Détails du profil
Informations personnelles :
Nom : Homme Idriss Neumann
Âge : 21
Localisation : France, Essonne (Île de France)

Informations professionnelles :
Activité : Développeur en SSII et étudiant au CNAM Paris (ingénieur SI)

Informations forums :
Inscription : février 2009
Messages : 1 705
Points : 4 346
Points : 4 346
Salut.
Pourquoi avoir mis en délestage plutôt qu'en résolu ? (ça joue dans les recherches pour les autres membres).
__________________
modérateur rubriques Linux/Unix et chat
ok.Idriss est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 23/09/2009, 11h51   #6
Invité de passage
 
Inscription : juillet 2009
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 11
Points : 1
Points : 1
J'avais posté ici car je voulais au départ une solution utilisant les fonctions de base disponible sur Unix.
N'ayant pas de réponse j'ai reposté ailleurs(ici) en acceptant d'autres languages et j'ai donc placé ce port en délestage à ce moment.
J'ai pu avoir une solution en ouvrant encore un post sur un fofo us(unix.com) et j'ai donc posté la solution dans mon 2e poste pour partager la solution.
Enfin ayant posté une réponse a mon tout premier post j'ai aussi posté la solution pour info.
En fait c'est la faute de Sinamone...lol
Donc je fais quoi ?
case
je laisse en délestage et je fais rien,
j'enlève le délestage et je vérifie la solution de sinamone
je met résolu et je fais rien,
jme gratte
andcase

@sinamone
j'ai pas encore testé ta solution car celle que j'ai fonctionne mais ça devrait arriver si j'oublie pas...

Dernière modification par mangalor ; 24/09/2009 à 11h38.
mangalor est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 24/09/2009, 11h37   #7
Invité de passage
 
Inscription : juillet 2009
Messages : 11
Détails du profil
Informations forums :
Inscription : juillet 2009
Messages : 11
Points : 1
Points : 1
Sinamone pourrais tu m'expliquer la commande sed que tu fais car je suis pas trés familier avec elle ?
sed "s/\(.\{5\}\)\(.\{20\}\)\(.\{5\}\)/\1;\2;\3;/g"

J'y connais rien du tout mais je dirais tu créé 3 commande que tu lances et tu rajoute un ;
Je dit ça car dans les faits j'ai 56 insertions de ; à faire mais avec des espacements différents de 5 et 20.....
mangalor est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/10/2009, 00h14   #8
Invité régulier
 
Inscription : septembre 2009
Messages : 6
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 6
Points : 6
Points : 6
Ha bon faut donc que tu ecrives les 50 champs a la main , nonnn !!

sed "s/\(.\{5\}\)\(.\{20\}\)\(.\{5\}\)/\1;\2;\3;/g"
l'expression reguliere du sed signifie:
" n'importe quel caractere " répété 5 fois
puis
" n'importe quel caractere " répété 20 fois
puis
" n'importe quel caractere " répété 5 fois
ensuite on réecrit les 3 enregistrements séparés cette fois par des ";"
IL faut donc que tu continues la suite de la meme facon

Ex:
sed "s/\(.\{5\}\)\(.\{20\}\)\(.\{5\}\)\(.\{60\}\)\(.\{45\}\)\(.\{2\}\)\(.\{67\}\)/\1;\2;\3;\4;\5;\6;\7;/g"

Bon aller, petit cadeau maison ) , pour ecrire la suite de facon "automatique", tu peux faire par exemple:

#!/usr/bin/ksh
LENGHT_FIELD="5 20 5 60 45 2 67" #liste qui definit la longueur des champs
j=1

for i in $LENGHT_FIELD
do
EXPR=$EXPR"\(.\{$i\}\)"
LIST_REC=$LIST_REC"\\\\$j;"
(( j = $j + 1 ))
done
echo "sed \"s/$EXPR/$LIST_REC/g\""
sinamone est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/10/2009, 11h09   #9
Invité régulier
 
Inscription : septembre 2009
Messages : 6
Détails du profil
Informations forums :
Inscription : septembre 2009
Messages : 6
Points : 6
Points : 6
Mon dernier post comporte une erreur.
ON ne peut pas utiliser plus de 9 enregistrements dans un sed.
Voici donc ce qu'il faut faire pour contourner cela, en gardant la construction de la commande sed de facon dynamique. Ca devient compliqué mais cette fois c'est abouti et ca fonctionne !!!

Code :
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
#!/bin/ksh

########### Variables a parametrer ###########
IN=TEXTE.txt
OUT=res.txt
lenght_ligne=899       # Le nombre de ligne souhaité - 1
set 5 20 5 60 2 2 5 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 766 1 1 2 #liste qui definit la longueur des champs qui doivent etre séparés par des ";"
NBRARG=`echo $#` 


########### On construit la commande SED de la forme " | sed s/expreg1/val1/ | sed s/expreg2/val2/ ..... " ###########
STEP=1
SED=1
while(( $NBRARG > 0 ))
do
        if [ $STEP -eq 1 -a $SED -ne 1 ];then
                EXPR="\(.*;\)"
                LIST_REC="\\\\$STEP"
        else
                EXPR=$EXPR"\(.\{$1\}\)"
                LIST_REC=$LIST_REC"\\\\$STEP;"
        fi
        (( STEP = $STEP + 1 ))
        if [ $STEP -gt 9 -o $NBRARG -eq 1 ];then
                CMD[$SED]=`echo "| sed \"s/$EXPR/$LIST_REC/\""`
                STEP=1
                (( SED = $SED + 1 ))
        fi
        shift
        NBRARG=$#
done

CMD='cat $IN | cut -c${i}-${j}'$( echo ${CMD[*]})


########### Boucle principale qui cree chaque ligne du nouveau fichier ###########
lenght_fic=$(cat $IN | wc -c)
i=1
while(( i < $lenght_fic ))
do
        (( j = i + $lenght_ligne ))
        eval $CMD >> $OUT
        (( i = i + $lenght_ligne + 1 ))
done
sinamone est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +1. Il est actuellement 21h35.


 
 
 
 
Partenaires

Hébergement Web