Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

sed: remplacer les dernieres lignes de fichiers par un mot...

27 réponses
Avatar
njko
Salut la liste!

Un petit message car je galère avec sed....
Je souhaiterais supprimer les 25 dernières lignes de plusieurs fichiers,
et y mettre à la place un simple mot.

D'apres ce que j'ai compris de la doc, j'ai tenté quelques commandes,
jamais bon.


sed -i -e "s/$-25/nouveaumot/g" *.php

par exemple.. me rajoute un nouveaumot à chaque ligne.

Comment dire à sed de remplacer les n dernieres lignes de différents
fichiers par un mot?
Quelqun-e aurait une piste?

Merci et bonne continuation!


Nicolas

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to debian-user-french-REQUEST@lists.debian.org
with a subject of "unsubscribe". Trouble? Contact listmaster@lists.debian.org

10 réponses

1 2 3
Avatar
Daniel Caillibaud
njko a écrit :
Salut la liste!

Un petit message car je galère avec sed....
Je souhaiterais supprimer les 25 dernières lignes de plusieurs fichiers,
et y mettre à la place un simple mot.



sed veut dire "stream editor", c'est pour éditer un flux, et par définition, un flux, on ne peut pas savoir s'il est bientôt fini ou pas, on s'en
aperçoit quand il est tari...
Quand sed lit une ligne, "il" ne peut donc pas savoir combien il en reste dans le fichier.


D'apres ce que j'ai compris de la doc, j'ai tenté quelques commandes,
jamais bon.

sed -i -e "s/$-25/nouveaumot/g" *.php



Mmm, tu as pas dû lire beaucoup de doc ;-)
Regarde http://ll.lairdutemps.org/linux/sed et les liens en début de page (il faut remettre à la main le bon n° version pour abs).

Comment dire à sed de remplacer les n dernieres lignes de différents
fichiers par un mot?



Directement, tu ne peux pas.

Quelqun-e aurait une piste?



- compter d'abord le nb de lignes
lignes=$(wc -l < fichier)
start=$((lignes - 25))

puis un truc genre

sed -e "${start}"',$ c ton_mot' < fichier > fichier.new
ou
sed -i .old -e "${start}"',$ c ton_mot' fichier

- mais sed est pas très utile dans ce cas, un simple

head -$start < fichier > fichier.new
echo ton_mot >> fichier.new

suffirait.

--
Daniel

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Jacques L'helgoualc'h
njko a écrit, mardi 23 décembre 2008, à 02:52 :
Salut la liste!



bonjour,

Un petit message car je galère avec sed....
Je souhaiterais supprimer les 25 dernières lignes de plusieurs fichiers,
et y mettre à la place un simple mot.

D'apres ce que j'ai compris de la doc, j'ai tenté quelques commandes,
jamais bon.

sed -i -e "s/$-25/nouveaumot/g" *.php



Tu devrais plutôt utiliser -i.old pour tes essais ;)

par exemple.. me rajoute un nouveaumot à chaque ligne.



« s/$-25/.../ » est une erreur, tu mélanges adresse de ligne, et regexp
à substituer...

Comment dire à sed de remplacer les n dernieres lignes de différents
fichiers par un mot?



Les n premières, c'est facile, donc tu pourrais passer par « tac » pour
lire ta source à l'envers, avant un « sed -e '1,25 s/.*/lemot/' ».

Quelqun-e aurait une piste?



Tu peux fouiner dans les trésors de http://sed.sf.net/, ou dans « info
sed », il me semble qu'il y a une astuce pour émuler tail...

Merci et bonne continuation!



de rien, amuse-toi bien,
--
Jacques L'helgoualc'h

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Jacques L'helgoualc'h
Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :
njko a écrit :


[...]
Comment dire à sed de remplacer les n dernieres lignes de différents
fichiers par un mot?



Directement, tu ne peux pas.



Mécréant ! Sed est Turing-complet, il /peut/ le faire :

~ $ echo {1..12} | sed 's/ /n/g' |
sed -nre 'H;${g;s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/;s/^n//p}'
IN MEMORIAM MAXI 25 LIGNES, AMEN

~ $ echo {1..42} | sed 's/ /n/g' |
sed -nre 'H;${g;s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/;s/^n//p}'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
IN MEMORIAM MAXI 25 LIGNES, AMEN

--
Jacques L'helgoualc'h

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Daniel Caillibaud
Jacques L'helgoualc'h a écrit :
Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :
njko a écrit :


[...]
Comment dire à sed de remplacer les n dernieres lignes de différents
fichiers par un mot?


Directement, tu ne peux pas.



Mécréant ! Sed est Turing-complet, il /peut/ le faire :

~ $ echo {1..12} | sed 's/ /n/g' |
sed -nre 'H;${g;s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/;s/^n//p}'
IN MEMORIAM MAXI 25 LIGNES, AMEN



Évidemment, mais là tu charge tout dans le holdspace et tu appliques une regex dessus, ça sort du concept "stream editor" (mais c'est possible), dans
la mesure où tu dois attendre d'avoir atteint la fin du fichier (en ayant tout chargé en attendant) pour commencer à travailler. Sur un petit fichier
ça va, sur un log de qq centaines de Mo c'est moins top ;-)

Bref, je pense que wc + head reste le plus adapté à ce cas de figure.

--
Daniel


PS: pour ceux qui veulent comprendre, un peu d'explications sur l'expression sed de Jacques (un script sed s'applique sur chaque ligne en entrée)
<script sed>
H; # ajouter la ligne courante au holdspace (mémoire tampon)
${ # si on est sur la dernière ligne, on exécute ce bloc
# récupérer le contenu du holdspace
g;
# remplacer la plus grande séquence constituée de 0 à 25 lignes se terminant par la fin de fichier
# par le texte IN MEMORIAM... (1re expression s/pattern/replace/
# remplacer les retour chariot en début de ligne par rien et imprimer le résultat de cette substitution
s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/;s/^n//p
}
</script sed>

les options sed sont
-n : n'imprimer les lignes reçues en entrée que si on le demande explicitement (avec p)
-r : il s'agit de regex étendues
-e : appliquer l'expression qui suit (entre apostrophes, pour que le shell n'interprête pas les $)

Je comprend d'ailleurs pas trop ce s/^n//p, un
sed -nre 'H;${g;s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/p;}'
revient au même non ?

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Kevin Hinault
------=_Part_83812_4568271.1230051010155
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Le 23 décembre 2008 17:05, Daniel Caillibaud a écrit
:

Jacques L'helgoualc'h a écrit :

Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :

njko a écrit :









Juste parce que ça m'amusait de le faire en perl :

$ perl -e 'while(<>){$i++;push(@buf,$_);print shift(@buf) if($i>25);}'
lefichier

J'écoute toute améliorations bien sûr ;)

Kévin

------=_Part_83812_4568271.1230051010155
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Le 23 décembre 2008 17:05, Daniel Caillibaud <span dir="ltr">&lt;<a hre f="mailto:"></a>&gt;</span> a écrit :<br><div class="gmail_quote"><blockquote class="gmail_quote" s tyle="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8e x; padding-left: 1ex;">
Jacques L&#39;helgoualc&#39;h a écrit :<br>
<div class="Ih2E3d"><blockquote class="gmail_quote" style="border-lef t: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1 ex;">
Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :<br>
<blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
njko a écrit :<br>
</blockquote>
</blockquote></div></blockquote></div><br><br>Juste parce que ça m&#39;am usait de le faire en perl :<br><br>$ perl -e &#39;while(&lt;&gt;){$i++;push (@buf,$_);print shift(@buf) if($i&gt;25);}&#39; lefichier<br><br>J&#39;éc oute toute améliorations bien sûr ;)<br>
<br>Kévin<br>

------=_Part_83812_4568271.1230051010155--

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Jacques L'helgoualc'h
Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 17:05 :
Jacques L'helgoualc'h a écrit :
Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :
njko a écrit :


[...]
Comment dire à sed de remplacer les n dernieres lignes de différents
fichiers par un mot?


Directement, tu ne peux pas.



Mécréant ! Sed est Turing-complet, il /peut/ le faire :

~ $ echo {1..12} | sed 's/ /n/g' |
sed -nre 'H;${g;s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/;s/^n//p}'
IN MEMORIAM MAXI 25 LIGNES, AMEN



Évidemment, mais là tu charge tout dans le holdspace et tu appliques une
regex dessus, ça sort du concept "stream editor" (mais c'est possible),
dans la mesure où tu dois attendre d'avoir atteint la fin du fichier (en
ayant tout chargé en attendant) pour commencer à travailler. Sur un petit
fichier ça va, sur un log de qq centaines de Mo c'est moins top ;-)



Oui, c'est un peu goret de tout lire avant de commencer à bosser (c'est
pour ça que je suggérais de chercher l'émulation de tail).

Il me semble que dans les trésors de http://sed.sf.net on peut trouver
une méthode de fenêtre glissante FIFO qui permet, appliquée ici,

- de stocker les 25 premières lignes ;

- puis écrire la première, l'effacer et ajouter la nouvelle en queue ;

- et faire la substitution demandée, une fois avalée la dernière ligne...


Bref, je pense que wc + head reste le plus adapté à ce cas de figure.



C'est sans doute plus simple, en effet --- même si on peut aussi
l'écrire avec Sed :) --- mais tu lis deux fois tout le fichier,
ce qui n'est pas indiqué avec un ruban, des cartes perforées,
une bande magnétique ou un pipe :P

PS: pour ceux qui veulent comprendre, un peu d'explications sur
l'expression sed de Jacques (un script sed s'applique sur chaque ligne
en entrée)
<script sed>
H; # ajouter la ligne courante au holdspace (mémoire tampon)
${ # si on est sur la dernière ligne, on exécute ce bloc
# récupérer le contenu du holdspace
g;
# remplacer la plus grande séquence constituée de 0 à 25 lignes se terminant par la fin de fichier
# par le texte IN MEMORIAM... (1re expression s/pattern/replace/
s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/



# supprimer le tout premier retour chariot en début de fichier
# (cf. plus bas, à cause de 1H), et imprimer le résultat
s/^n//p

}
</script sed>

les options sed sont
-n : n'imprimer les lignes reçues en entrée que si on le demande explicitement (avec p)
-r : il s'agit de regex étendues



... sinon il faudrait taper
s/(n[^n]*){0,25}$/...

et quatre contre-obliques séparées, c'est moins agréable que « -r
espace » sur un clavier azerty.

-e : appliquer l'expression qui suit (entre apostrophes, pour que le shell n'interprête pas les $)

Je comprend d'ailleurs pas trop ce s/^n//p, un
sed -nre 'H;${g;s/(n[^n]*){0,25}$/nIN MEMORIAM MAXI 25 LIGNES, AMEN/p;}'
revient au même non ?



Non, le H introduit un n parasite devant la première ligne ---
je ne le nettoie qu'ensuite, car il m'épargne un (^|n) au début
des lignes à remplacer...

Pour ne stocker que le fichier dans le holdspace, il faudrait un

1h;1!H

--
Jacques L'helgoualc'h

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Jacques L'helgoualc'h
Kevin Hinault a écrit, mardi 23 décembre 2008, à 17:50 :
Le 23 décembre 2008 17:05, Daniel Caillibaud a écrit
:

> Jacques L'helgoualc'h a écrit :
>
>> Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :
>>
>>> njko a écrit :
>>>
>>

Juste parce que ça m'amusait de le faire en perl :

$ perl -e 'while(<>){$i++;push(@buf,$_);print shift(@buf) if($i>25);}'
lefichier

J'écoute toute améliorations bien sûr ;)



perl -e 'while(<>){,$_;print if++$i>25}print"Le mot de la finn"'

--
Jacques L'helgoualc'h

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Kevin Hinault
------=_Part_86728_26357288.1230059733980
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

Le 23 décembre 2008 20:00, Jacques L'helgoualc'h
<lhh+<lhh%
a écrit :




perl -e 'while(<>){,$_;print if++$i>25}print"Le mot de la
finn"'




Arf oui merci je l'avais oublié ce mot :)

------=_Part_86728_26357288.1230059733980
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

<br><br><div class="gmail_quote">Le 23 décembre 2008 20:00, Jacques L&# 39;helgoualc&#39;h <span dir="ltr">&lt;<a href="mailto:lhh% ee.fr">lhh+</a>&gt;</span> a écrit :<br><blockquote class ="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin : 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>perl -e &#39;while(&lt;&gt;){,$_;print if++$i&gt;25}print &quot;Le mot de la finn&quot;&#39;<br>
<br>
</blockquote></div><br clear="all">Arf oui merci je l&#39;avais oublié ce mot :)<br><br>

------=_Part_86728_26357288.1230059733980--

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Arnaud Delobelle
Jacques L'helgoualc'h <lhh+ writes:

Kevin Hinault a écrit, mardi 23 décembre 2008, à 17:50 :
Le 23 décembre 2008 17:05, Daniel Caillibaud a écrit
:

> Jacques L'helgoualc'h a écrit :
>
>> Daniel Caillibaud a écrit, mardi 23 décembre 2008, à 10:15 :
>>
>>> njko a écrit :
>>>
>>

Juste parce que ça m'amusait de le faire en perl :

$ perl -e 'while(<>){$i++;push(@buf,$_);print shift(@buf) if($i>25);}'
lefichier

J'écoute toute améliorations bien sûr ;)



perl -e 'while(<>){,$_;print if++$i>25}print"Le mot de la f inn"'



Version lisible:

$ python -c "import sys
acc = []
for line in open(sys.argv[1]):
acc.append(line)
if len(acc) > 25: print acc.pop(0)
print 'Le mot de la fin'
" monfichier

;)

--
Arnaud

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
Avatar
Jacques L'helgoualc'h
Jacques L'helgoualc'h a écrit, mardi 23 décembre 2008, à 18:53 :
[...] chercher l'émulation de tail.

Tout bêtement dans « info sed »...

Il me semble que dans les trésors de http://sed.sf.net on peut trouver
une méthode de fenêtre glissante FIFO qui permet, appliquée ici,

- de stocker les 25 premières lignes ;

- puis écrire la première, l'effacer et ajouter la nouvelle en queue ;

- et faire la substitution demandée, une fois avalée la dernière ligne...



sed -ne '1h;2,25H;26,${H;g;P;s/^[^n]*n//;h};$aLe mot de la fin.'
.........<- un -> <--------- deux ----------> <----- trois ----->

66 caractères, contre 79 avec Perl :P
--
Jacques L'helgoualc'h

--
Lisez la FAQ de la liste avant de poser une question :
http://wiki.debian.org/DebFrFrenchLists
Vous pouvez aussi ajouter le mot ``spam'' dans vos champs "From" et
"Reply-To:"

To UNSUBSCRIBE, email to
with a subject of "unsubscribe". Trouble? Contact
1 2 3