Newsgroup: it.comp.os.linux.iniziare
Titolo: sed: stringa sostitutiva contenente spazi

Sto buttando giů uno script bash per filtrare
gli headers degli articoli da postare su
usenet.
In particolare vorrei rielaborare l'header
"Date:" correggendo il time zone.
Stringi stringi veniamo alla domanda:
- stringa di partenza
 Date: Fri, 18 Jun 2010 07:35:59 -0000
- stringa modificata:
  la data attuale $(date -R) in formato rfc-2822
 
 Date: Fri, 18 Jun 2010 10:31:21 +0200
Va bč, ora non corrispondono gli orari ma č
un esempio, quindi non ha importanza.
Il comando seguente da console funge:
__________________________________________
 echo "Fri, 18 Jun 2010 10:31:21 +0200" \
 |sed s/^Date:.*/"$(date -R)"/
 Fri, 18 Jun 2010 10:31:21 +0200
________________________________
Il problema arriva quando metto il tutto in
uno script. La stringa da modificare č
presente in $TEMPFILE.
DATE="Date: $(date -R)"
FIXDATE=s/^Date:.*/"${DATE}"/
sed $FIXDATE $TEMPFILE
ma non torna...
Il problema sta molto probabilmente nel fatto
che la stringa sostituiva (a destra, per
capirci) contiene degli spazi.
Una versione che funziona:
DATE="Date: $(date -R)"
sed s/^Date:.*/"${DATE}"/ $TEMPFILE
Perň avrei voluto capire come mai non funge
con la variabile FIXDATE. E come
eventualmente farlo funzionare anche in quel
modo.
Grazie in anticipo

 eventualmente farlo funzionare anche in quel modo.
Nel tuo caso puoi usare "$FIXDATE".
lem@lappybaby:~$ echo "Date:baraus"$(date) |sed "$FIXDATE"
Date: Fri, 18 Jun 2010 13:19:14 +0200
-- 
Bye, Lem
Ceterum censeo ISLAM esse delendum
____________________________________________________________________________
Non sprecare i cicli idle della tua CPU: 
http://boinc.berkeley.edu/index.php

 Date: Fri, 18 Jun 2010 13:19:14 +0200
Eppure non era difficile, come ho fatto a non
vederlooo!
Va bè, grazie Lem, ora dovrei fare la stessa
cosa ma filtrando N messaggi, quindi il
$TEMPFILE di prima diventa "per ogni
messaggio che trovi nella coda di uscita".
Pensavo a qualcosa del genere:
find $OUTSPOOL "\$*" -exec sed -i "${FIXDATE}" "{}" \;
Non l'ho testato...
E poi vi è (tra gli altri) un bug semantico
bello grosso:
se per caso il corpo del messaggio contenesse
una riga che iniziasse per "Date:", la riga
verrebbe magicamente tramutata in una stapa
della data secondo rfc-2822.
Date: 5 mele
      6 pere
Ecco, una cosa del genere perderebbe senso.
Allora sarebbe il caso di istruire sed per
sostituire solo la prima occorrenza del
pattern e disinteressarsi del resto del
testo. Ovviamente senza sapere a priori
in quale riga sta l'header Date da
modificare.
Che dite si potrà fare no?
Cioè intendo con le opzioni di sed, sto
spulciando il man sed al paragrafo addresses,
ma forse sarebbe meglio affidarsi a google,
come al solito capisco più dagli esempi che
dai dizionari... bè se aveste la soluzione a
portata di mano, dite pure!

 spulciando il man sed al paragrafo addresses,
Ma per modificare degli headers non sarebbe meglio usare formail, che è
nato per quello?
-- 
Massimo Bacilieri AKA Crononauta

 meglio usare formail, che � nato per quello?
Pu� darsi, ma conosco meglio sed. Comunque
grazie del consiglio.
Nel frattempo ho trovato una soluzione:
________________________
DATE="Date: $(date -R)"
FIXDATE="1,/^Date:.*/s/^Date:.*/${DATE}/"
sed "$FIXDATE" $TEMPFILE
________________________
Ha il problema che se per disgrazia l'header
datesi trovasse nella prima riga, allora
verrebbe considerata da trasformare anche
l'eventuale riga successiva corrispondente
al pattern {^Date:.*}.
L'aternativa che ho trovato vale solo per
la versione GNU di sed:
FIXDATE="0,/^Date:.*/s/^Date:.*/${DATE}/"
Questa non fallisce. Almeno non nel caso di
cui sopra.
Comunque l'header Date nei miei messaggi da
postare non sembra mai messo in prima riga,
quindi anche la versione standard di sed
dovrebbe bastare allo scopo.

 grazie del consiglio.
No è che tutto il casino che vuoi fare, con formail si riduce banalmente a:
formail -I "Date: $(date -R)" <input > output
senza impazzire tanto...



Mi piace più sed.
Grosso modo so già come funziona a grandi
linee. Se un domani devo mettere mano allo
script, l'ho fatto io e probabilmente riesco
più facilmente a venirne a capo.
Ora deduco che formail prenda l'header "Date:"
che c'è già, lo butta via e vi sostituisce il
valore della data attuale "Date: balabla".
Ma per come devo utilizzarlo io non mi basta,
cioè non è così facile per me sostituirlo a
sed, vuoi perchè devo fare lo stesso lavoro
per tutti gli articoli dello spool, e "sed -i"
da questo punto di vista è piuttosto comodo.
Vuoi perchè il problema può essere anche
leggermete diverso. E mi spiego.
Se prima parlavo di sostituire l'header date
col valore della data attuale.
Adesso voglio complicare la cosa:
l'header date del messaggio contiene la data
dell'istante di post in locale, il momento in
cui ho finito di editare l'articolo.
quando posto l'articolo in remoto l'istante e
il valore di date sarà differente.
Ma io vorrei che il mio header date
contenesse il reale istante in cui ho scritto
l'articolo, non quello in cui la coda
d'uscita dello spool viene inviata al server
remoto.
Quindi. invece del semplice comando $date.
Occorre prendere il valore simil utc sballato
di due ore, che l'header Date contiene.
Ad esempio:
Fri, 18 Jun 2010 07:35:59 -0000
E sostituirvi:
date -d "Fri, 18 Jun 2010 07:35:59 -0000" -R
che diventetrà:
Fri, 18 Jun 2010 09:35:59 +0200
Purtroppo il programma che uso include nei
messaggi l'header "Date:" qualora ne siano
sprovvisti, però ha la brutta abitudine di
metterlo con quel formato simil utc.
(snsend/snstore)
Non avendo trovato alternative ho pensato di
lavorarci a posteriori al momento del post
prima di lanciare il comando per
l'invio/ricezione messaggi (snget).
Ora alla fine il comando di sed sarebbe
qualcosa del genere:
sed -i "0,/^Date:[ ].*/s/[a-z]*,.*$/$(date -R -d "&")/" ${FILE}
però non torna: quell' "&" in qualche modo
non viene visto come una data regolare.
eppure se metto $(echo "&") vedo la data,
quella vecchia e scorretta, ovvio, ma la vedo.
Quale sarebbe la giusta direttiva?


Facebook: Massimo Bacilieri

 Questo è masochismo :-)
Ok, la tua risposta mi risolve il problema.
Vorri però capire come mai con sed non
funziona come mi aspetterei...
Consideriamo di avere il seguente file di
testo:
______________________________________
# cat provevarie/filtermess.txt
Date: Fri, 18 Jun 2010 07:35:59 -0000
Bytes: 32
Lines: 1
Date: Fri, 18 Jun 2010 07:35:59 -0000
Prova correzzione header Date:
.
__
E di voler sostituire nella prima riga
che contiene "^Date:" il formato della data
portando il time zone al fuso +2, il comando
se è settato bene l'orario del sistema, è
banalmente:
date -R -d "Fri, 18 Jun 2010 07:35:59 -0000"
Il comando da dare in pasto a sed che avevo
pensato dsarebbe stato qualcosa del genere:
"0,/^Date:[ ].*/s/\([A-Za-z]\{3\},.*$\)/$(date -R -d \1)/"
però non funziona:  in qualche modo non
riesco a ripescare la stringa intercettata a
sinistra in modo che sia digeribile da
comando "date".
La cosa strana è che se sostituissi a date -R
ecc, un semplice echo tipo:
$(echo "|==============>|""\1")
allora mi metterebbe in evidenza la stringa
intercettata.
Ok. ho pensato ad un problema di newline
intercettato in più che magari da fastidio a
date, oppure non riesco bene a capire il
giusto quoting da usare...
Spero possiate darmi una dritta, grazie in
anticipo.