[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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



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


Reply to: