Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 31/07/2014, à 23:03

Tomzz

[Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Bonsoir,

Je cherche, dans un script shell, à supprimer toutes les lignes d'un fichier précédant la ligne contenant une chaîne.
Pour être plus clair, j'ai un fichier du type:

#001#blablabla...
#002#blablabla...
#003#blablabla...
#004#blablabla...
#005#blablabla...
...

et je veux supprimer toutes les lignes précédent celle contenant #003# (en incluant la #003# si possible, sinon je m'adapterai) et donc obtenir:

#004#blablabla...
#005#blablabla...
....

Mon fichier est classé par les champs #00n# il ne peut pas y avoir de doublons mais il peut y avoir des trous dans la numérotation.
Est-ce possible avec un grep, ou éventuellement awk ?

Dernière modification par Tomzz (Le 01/08/2014, à 11:28)

Hors ligne

#2 Le 31/07/2014, à 23:40

Postmortem

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Salut,

awk 'i;/#003#/{i=1}' fichier

Par contre, j'ai pas testé, j'ai pas awk sur mon tel.


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#3 Le 31/07/2014, à 23:55

Compte anonymisé

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

... ou

sed -i '1,3d' fichier

#4 Le 01/08/2014, à 06:03

pingouinux

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Bonjour,
Avec sed, je ferais plutôt ceci :

sed  '1,/#003#/d' fichier

Hors ligne

#5 Le 01/08/2014, à 08:00

Compte anonymisé

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Le n de "#00n# " correspond au numéro de ligne, donc la chaîne "#00n#" n'apporte pas grand-chose de plus sinon rien, sauf que c'est plus générique.

#6 Le 01/08/2014, à 08:12

pingouinux

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

@φlip :

Tomzz #1 a écrit :

Mon fichier est classé par les champs #00n# il ne peut pas y avoir de doublons mais il peut y avoir des trous dans la numérotation.

Le champ au début de la ligne numéro n n'est pas forcément #00n#.

Hors ligne

#7 Le 01/08/2014, à 08:39

Compte anonymisé

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Tomzz a écrit :

Mon fichier est classé par les champs #00n# il ne peut pas y avoir de doublons mais il peut y avoir des trous dans la numérotation.

C'est plutôt le fait qu'il peut y avoir des trous dans la numérotation qui m'a échappé.

#8 Le 01/08/2014, à 09:03

Postmortem

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

φlip a écrit :
Tomzz a écrit :

Mon fichier est classé par les champs #00n# il ne peut pas y avoir de doublons mais il peut y avoir des trous dans la numérotation.

C'est plutôt le fait qu'il peut y avoir des trous dans la numérotation qui m'a échappé.

Et donc que le champ au début de la ligne numéro n n'est pas forcément #00n# !! tongue


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#9 Le 01/08/2014, à 09:40

Tomzz

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Bonjour,
Merci pour toutes ces réponses.
et toutes mes excuses parce que j'ai mal posé mon problème.
En fait le fichier est un CVS ou chaque ligne contient 294 champs (ou 255 selon les versions) encadrés par des "" et séparés par !#.
La position des champs et toujours la même (si 255 champs se sont les 256 à 294 qui sont ignorés).
Le n° 00n (en fait 0000n) est unique et toujours présent dans chaque ligne, mais il peut être répété 3 fois dans la même ligne et fait toujours 5 digit de long: 00001, 00002...00101...99999

Le fichier est trié par ce n°, mais il peut y avoir des trous dans la numérotation ( par ex j'ai lignes 00002 à 00010 mais pas de ligne 00001, 00005...)

Contrairement à ce que j'ai écrit plus haut, il n'est pas dans le premier champ de la ligne mais dans le second et dans les champs 112 et 175 mais j'aimerai ne m’intéresser qu'au second champs.

Un exemple réel (mais tronqué) du fichier:

"tomzz"!#"00004"!#"blabla"!#"bloblo....
"tomzz"!#"00008"!#"blabla"!#"bloblo....
"tomzz"!#"00015"!#"blabla"!#"bloblo....
"tomzz"!#"00032"!#"blabla"!#"bloblo....
"tomzz"!#"00045"!#"blabla"!#"bloblo....
"tomzz"!#"00085"!#"blabla"!#"bloblo....
"tomzz"!#"00086"!#"blabla"!#"bloblo....
"tomzz"!#"00087"!#"blabla"!#"bloblo....

Je voudrai donc, par exemple, supprimer toutes les lignes qui précèdent celle contenant !#"00045"!#, y compris la ligne !#"00045"!# si possible.

Je vais tester les solutions proposées plus haut maintenant wink

Hors ligne

#10 Le 01/08/2014, à 09:46

pingouinux

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

C'est la même chose :

$ sed  '1,/!#"00045"!#/d' fichier
"tomzz"!#"00085"!#"blabla"!#"bloblo....
"tomzz"!#"00086"!#"blabla"!#"bloblo....
"tomzz"!#"00087"!#"blabla"!#"bloblo....

Hors ligne

#11 Le 01/08/2014, à 10:12

Tomzz

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Alors, après tests les deux commandes fonctionnent:

awk 'i;/!#"00045"!#/{i=2}' $HOME/fichier-in.csv > $HOME/fichier-out.csv

sed  '1,/!#"00045"!#/d' $HOME/fichier-in.csv > $HOME/fichier-out.csv

Le 1 dans la commande sed est intéressant car il dit à partir de quelle ligne on coupe ( si 2 je garde la première ligne et je supprime toute les suivantes jusqu'à ce que je rencontre !#"00045"!# )
Je ne vais pas m'en servir là, mais surement pour plus tard.

En revanche, pour awk, je ne comprend pas le {i=2}, je l'ai remplacé par {i=3} et ça ne fait aucune différence.

Dans l'absolu, quelle est la meilleure commande, je crois avoir lu ailleurs que sed était plus rapide que awk.

Dernière modification par Tomzz (Le 15/08/2014, à 22:18)

Hors ligne

#12 Le 01/08/2014, à 11:09

Postmortem

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

La commande awk suivante :

awk 'i;/#003#/{i=1}' fichier

Est équivalente à ceci mais qui est plus compréhensible :

awk ' i != 0 {print $0}
      $0 ~ /#003#/ { i=1 }' fichier

On affiche la ligne que si i est différent de 0.
i prend la valeur 1 quand on rencontre #003# dans la ligne.
Le fait de mettre la partie affichage avant la partie qui change la valeur de i fait que la 1ère ligne contenant la valeur recherchée n'est pas affichée.
Si on veut que la ligne contenant la valeur recherchée soit affichée, il suffit d'inverser :

awk '/#003#/{i=1};i' fichier

On aurait très bien pu mettre i=2, i=3 ou n'importe quel nombre différent de 0.

Édit :
Concernant la rapidité, awk est une flèche... Après tout dépend de ce qu'on met dedans... Tout comme dans sed !
Les 2 sont faits pour traiter des fichiers textes donc à toi de voir et de tester.
L'avantage de awk, c'est que tu peux travailler plus facilement sur des champs, ce qui est le cas d'un fichier csv.

Dernière modification par Postmortem (Le 01/08/2014, à 11:12)


Mot' a dit : « Un Hellfest sans Slayer, c'est comme une galette-saucisse sans saucisse ! »

Hors ligne

#13 Le 01/08/2014, à 11:28

Tomzz

Re : [Résolu]Supprimer toutes ligne précédant la ligne contenant une chaine

Merci wink
résolu

Hors ligne