Newsgroup: it.comp.os.linux.iniziare
Titolo: comando SED come funziona?

So che il comando SED potrebbe essere utilizzato (insieme alle
espressioni regolari) per l'estrapolare dei dati da un file: ad
esempio se si ha un file con molti caratteri e numeri e io voglio solo
i caratteri fra una  "r" e una "g" come posso fare?
Grazie in anticipo, Mario.

 Grazie in anticipo, Mario.
$ cat pippo
qwerRRRRRRRRRRRRRgqwe
aaarXXXXXXXgtytyui
bssssrFFFFFggddddd
$ cat regole
s/^.*r//
s/g.*$//
$ cat pippo | sed -f regole >file2
$ cat file2
RRRRRRRRRRRRR
XXXXXXX
FFFFF
s/^.*r//
significa sostituisci (s) l'espressione a /^.*r/ con niente (//).
E l'espressione da sostituire parte da inizio riga (^) e comprende
qualunque seguenza di caratteri (.*) fino alla prima "r"
Il $ rappresenta invece il carattere di fine riga.
ciao, andrea


The majority of the stupid is invincible and guaranteed for all time.
The terror of their tyranny, however, is alleviated by their lack of
consistency.
                -- Albert Einstein

$ cat pippo | sed -f regole >file2
hmmmm.... non e' molto sicuro. Se nell'universo esistono anche cose come:
  bssssrFFFFFddddd
oppure:
  bssssFFFFFggddddd
o anche:
  bssssFFFFFddddd
ti ritrovi con:
  FFFFFddddd   
  bssssFFFFF
  bssssFFFFFddddd
che NON sono 'i caratteri fra una  "r" e una "g"' in quella riga[1].
Una strada puo' essere filtrare preventivamente le righe che non contengono
nulla da estrarre. Si puo' usare un grep in pipe prima del sed, con una
regoletta del genere: /^.*r([^g]+)g.*$/; ma si puo' anche fare tutto in
sed, con un filtrino un po' piu' complesso. Solo, in questo momento non mi
ricordo e non ho modo di controllare la sintassi esatta.
Ciao.
[1] Tra l'altro, anche la domanda e' un po' ambigua sul fatto se la "r" e
la "g" debbano o no essere sulla stessa riga, e se si voglia la prima serie
di caratteri o tutte le occorrenze (cioe', se in presenza della stringa
"bssssrAAAgddrBBBgddd" si voglia estrarre solo "AAA" o anche "BBB").

 
Ok, io ero partito dall'ipotesi semplicistica cheper ogni riga
esistesse una e una sola "r", seguita da una e una sola "g".
In genere, problemi di questo tipo derivano dalla necessita`
di elaborare l'output di qualcosa che e` stato predisposto 
per usare i delimitatori a ragion veduta.
Questo nuovo file "regole" va gia` un po' meglio:
 /r.*g/!d
s/^.*r\(.*\)g.*$/\1/
prima cancella (d) le righe che non (!) contengono r seguito
da g (/r.*g/);
poi individua in ogni riga la sequenza contenuta tra r e g 
(una parentesi preceduta da \ delimita un campo da usare in blocco )  
la memorizza nel primo stak (\1) e la sosituisce all'intera riga.
Altrimenti devi complicare tutto con dei filtri o passare
a strumenti piu` complessi come awk o perl.
In ogni caso se dovesse usare queste cose per problemi di lavoro
e` sempre meglio fare un passaggio di grep o sed che gli individui
eventuali righe anomale e gliele segnali.
Per esempio, se voglio anche dividerle per tipologia: 
sed -n '/r.*r/p' pippo >righe-con-2-r
sed -n '/g.*g/p' pippo >righe-con-2-g
sed -n '/g.*r/p' pippo >righe-con-g-prima-di-r
sed '/[gr]/d' pippo    > righe-senza-r-ne-g.
sperando di non aver fatto errori stupidi: non le ho testate.
mostra quelle con 2 r
Non mi accontenterei di _non_ lavorare sulle righe sbagliate,
vorrei anche accertarmi che non esistono
ciao, andrea
PS un buon micro-manuale di sed e`
http://www.cornerstonemag.com/sed/sed1line.txt


http://www.cornerstonemag.com/sed/sed1line.txt
Ecco, appunto, speriamo che ci siano esempi..
-- 
Ci sentiamo  |  Remigio Zedda  || Attenzione! campo "From:" alterato
ciao Remigio |                 ||==> E-mail: 
remi...@tiscalinet.it
-------------|      ..si` d'accordo.. ma con la Deb e` un'altra cosa!
/* Linux 2.2.17 su Debian 2.2 Potato */

 
sono _solo_ esempi :-)

 
In sed , vi, less bisogna stare attenti perche' 
"*" non significa "qualunque sequenza di caratteri",
ma "qualunque ripetizione del carattere precedente" anche _vuota_
"." significa qualunque carattere
Quindi "R.*G" trova tutte le occorrenze del tipo
a)  qualcosaRdfghythjkjGqualcos'altro
b)  qualcosaRGqualcos'altro
Mentre "R..*G" trova solo quelle che contengono qualcosa
tra R e G (la stringa a e non la stringa b) !
Infine "RR*" trova solo le sequenze di almeno una R.
Come vedi questo uso di * sara` poco intuitivo
ma si rivela molto duttile.
Nel tuo caso cercavi una sequenza di inizi riga, seguita da una
sequenza  di r e da una sequenza di g e chiusa da un 
fine riga. Le sequenze possone essere anche vuote.
ciao, Andrea

"." significa qualunque carattere
Si`, pensa che lo sapevo ma non ci pensavo, abituato a bash. E cosi`
come loro, ho visto che vanno anche anche awk e grep. Cmq poi, tra
vedere e non vedere, testavo sempre anche la tua espressione col punto.
THNX!


sono _solo_ esempi :-)
Preso, ottimo. THNX!
