OVH Cloud OVH Cloud

Enlever des lignes d'un fichier

13 réponses
Avatar
amorit
bonjour,
je cherche en une commande =E0 enlever d'un fichier texte des lignes
correspondant =E0 un masque.
Lorsque j'utilise la commande suivante :
cat nom_du_fichier |grep -v texte_a_enlever
j'obtient =E0 l'=E9cran le r=E9sultat voulu, mais lorsque j'ajoute :
cat nom_du_fichier |grep -v texte_a_enlever >nom_du_fichier
cel=E0 le vide
Qqun aurait-il la solution ?
merci d'avance

10 réponses

1 2
Avatar
TiChou
Dans le message
<news:,
** tapota sur f.c.o.l.configuration :

bonjour,


'jour,

je cherche en une commande à enlever d'un fichier texte des lignes
correspondant à un masque.


Pourquoi obligatoirement en une commande ?

Lorsque j'utilise la commande suivante :
cat nom_du_fichier |grep -v texte_a_enlever


UUoC ! (Google, tout ça)

j'obtient à l'écran le résultat voulu, mais lorsque j'ajoute :
cat nom_du_fichier |grep -v texte_a_enlever >nom_du_fichier
celà le vide


Normal, car la redirection '>nom_du_fichier' vide le fichier nom_du_fichier
avant même que la commande 'grep' reçoit tout son contenu.

Qqun aurait-il la solution ?


grep -v texte_a_enlever < nom_du_fichier > nom_du_fichier.tmp ;
mv nom_du_fichier.tmp nom_du_fichier

Ou sinon en utilisant une version récente de GNU sed :

sed -i '/texte_a_enlever/d' nom_du_fichier

merci d'avance


De rien.

--
TiChou

Avatar
David LE BOURGEOIS
bonjour,


Bonjour.

je cherche en une commande à enlever d'un fichier texte des lignes
correspondant à un masque.
Lorsque j'utilise la commande suivante :
cat nom_du_fichier |grep -v texte_a_enlever


UUOC.
$ grep -v text_a_enlever nom_du_fichier

j'obtient à l'écran le résultat voulu, mais lorsque j'ajoute :
cat nom_du_fichier |grep -v texte_a_enlever >nom_du_fichier
celà le vide


Curieux, moi j'obtiens :

$ cat fic
bonjour
bonsoir
$ cat fic | grep -v bonsoir > fic
$ cat fic
bonjour

Qqun aurait-il la solution ?


Avec sed ?

$ cat fic
bonjour
bonsoir
$ sed -i '/bonsoir/d' fic
$ cat fic
bonjour

--
David LE BOURGEOIS

Avatar
amorit
Merci beaucoup,
Je venais de trouver sed (merci pour la syntaxe précise) et j'apprend
le role de ;
bravo !
Avatar
tmartin
"" wrote in message
:
cat nom_du_fichier |grep -v texte_a_enlever >nom_du_fichier
celà le vide


Car l'entrelacement entre le moment où cat va lire le fichier et le moment
où >nom_de_fichier va le tronquer n'est pas vraiment clair et je ne sais
pas vraiment tout ce qui peut arriver. Pour contourner ce problème, il
suffit d'obtenir un descripteur sur le fichier d'origine (au hasard, par
exemple le 3, suffit d'en choisir un qui ne soit pas occupé), puis supprimer
le nom du dossier, afin d'être sûr que la sortie de grep ne vienne pas en
conflit dessus

exec 3<nom_du_fichier &&
rm nom_du_fichier &&
grep -v texte_a_enlever <&3 >nom_du_fichier &&
exec 3<&-

Avatar
lhabert
Thierry Martinez :

cat nom_du_fichier |grep -v texte_a_enlever >nom_du_fichier


Car l'entrelacement entre le moment où cat va lire le fichier et le moment
où >nom_de_fichier va le tronquer n'est pas vraiment clair et je ne sais
pas vraiment tout ce qui peut arriver.


Bah les possibilités sont assez claires. On a deux process lancés :
- un shell qui doit exécuter « cat fichier »
- un shell qui doit exécuter « ... > fichier », dont l'une des premières
actions va être d'écrabouiller le fichier.

Si le deuxième process a la main en premier suffisament longtemps, il va
avoir le temps de lire un bout du fichier avant que le deuxième ne
l'écrabouille. Mais ça ne peut pas durer très lontemps, parce que, ce qu'il
lit sur le fichier, il le recopie sur sa sortie, et sa sortie est un pipe
dont personne ne lit encore la sortie (on suppose que le deuxième processus
ne reçoit pas la main), et donc il va remplir le buffer du pipe, et ça va
finir par bloquer, et le deuxième process finira bien par avoir la main un
jour.

Donc il peut se passer tout intermédiaire entre :
- le fichier est vide avant que cat commence à le lire
- cat arrive à lire sur le fichier la taille du buffer du pipe (enfin, cat a
son buffer à lui, donc ça serait plutôt le premier multiple de la taille du
buffer de cat qui soit plus grand que le buffer du pipe).

Pour contourner ce problème, il suffit d'obtenir un descripteur sur le
fichier d'origine (au hasard, par exemple le 3, suffit d'en choisir un qui
ne soit pas occupé), puis supprimer le nom du dossier, afin d'être sûr que
la sortie de grep ne vienne pas en conflit dessus

exec 3<nom_du_fichier &&
rm nom_du_fichier &&
grep -v texte_a_enlever <&3 >nom_du_fichier &&
exec 3<&-


En effet, mais c'est un peu acrobatique, si on se plante dans la regexp et
que l'on perd tout le contenu du fichier, on se sent testé. Perso, je passe
toujours par un fichier intermédiaire, et il m'est arrivé plus d'une fois de
m'en louer...


Avatar
lhabert
David LE BOURGEOIS :

UUOC.


Traduction : « Useless Use Of Cat ». Tu utilises cat pour recopier un
fichier dans l'entrée d'un autre process, alors qu'il est possible de lier
directement le fichier à l'entrée du process :

grep -v blah < nom_du_fichier

Et d'ailleurs, la plupart des programmes lisant sur leur stdin peuvent
prendre en argument des noms de fichiers, comme David l'a montré.

Curieux, moi j'obtiens :

$ cat fic
bonjour
bonsoir
$ cat fic | grep -v bonsoir > fic
$ cat fic
bonjour


L'explication est sans doute dans le message de Thierry et dans ma réponse à
lui.

Avatar
Stéphan Peccini

Thierry Martinez :

cat nom_du_fichier |grep -v texte_a_enlever >nom_du_fichier



Donc il peut se passer tout intermédiaire entre :
- le fichier est vide avant que cat commence à le lire
- cat arrive à lire sur le fichier la taille du buffer du pipe (enfin, cat
a son buffer à lui, donc ça serait plutôt le premier multiple de la taille
du buffer de cat qui soit plus grand que le buffer du pipe).


Il me semble que le fichier sera toujours vide. Si je me rappelle de vieux
souvenirs, lorsque l'on a un pipe, c'est le processus de droite qui est
créé en premier avec sa redirection puis le processus de gauche. Mais bon,
mes souvenirs à ce sujet sont limite "effacement". Si quelqu'un peut
m'éclairer ...

--
Stephan Peccini
PhotoNature : <URL:http://www.photonature.fr>



Avatar
lhabert
Stéphan Peccini :

Si je me rappelle de vieux souvenirs, lorsque l'on a un pipe, c'est le
processus de droite qui est créé en premier avec sa redirection puis le
processus de gauche.


Ça doit dépendre énormément du shell. De toutes manières, que le process
soit créé en premier ou en deuxième, peu importe, le scheduling peut faire
n'importe quoi, a priori.

Avatar
Stéphan Peccini

Stéphan Peccini :

Si je me rappelle de vieux souvenirs, lorsque l'on a un pipe, c'est le
processus de droite qui est créé en premier avec sa redirection puis le
processus de gauche.


Ça doit dépendre énormément du shell.


Possible et sûrement probable.

De toutes manières, que le process
soit créé en premier ou en deuxième, peu importe, le scheduling peut faire
n'importe quoi, a priori.


Si c'est celui de droite qui est créé en premier, la redirection vide le
fichier avant que la commande de gauche ne soit lancée ; donc celle de
gauche ne voit qu'un fichier vide.

--
Stephan Peccini
PhotoNature : <URL:http://www.photonature.fr>


Avatar
Stéphan Peccini

Stéphan Peccini :

Si je me rappelle de vieux souvenirs, lorsque l'on a un pipe, c'est le
processus de droite qui est créé en premier avec sa redirection puis le
processus de gauche.


Ça doit dépendre énormément du shell. De toutes manières, que le process
soit créé en premier ou en deuxième, peu importe, le scheduling peut faire
n'importe quoi, a priori.


J'ai essayé cela :

[ all]$ cp /etc/hosts /tmp/hotes
[ all]$ cat /tmp/hotes | (sleep 5 && grep -v harkita
/tmp/hotes)
[ all]$ more /tmp/hotes

# Do not remove the following line, or various programs
# that require network functionality will fail.
127.0.0.1 localhost.localdomain localhost
[ all]$ cp /etc/hosts /tmp/hotes
[ all]$ cat /tmp/hotes | (sleep 5 && grep -v harkita)
/tmp/hotes
[ all]$ more /tmp/hotes

[ all]$

Peut on en tirer une conclusion ?

--
Stephan Peccini
PhotoNature : <URL:http://www.photonature.fr>


1 2