[Risolto] [awk] Stampa di N paragrafi ogni M

Linguaggi di programmazione: php, perl, python, C, bash e tutti gli altri.
Scrivi risposta
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

[Risolto] [awk] Stampa di N paragrafi ogni M

Messaggio da vaeVictis »

Ciao a tutti!

Devo estrarre da un file di testo un numero N di paragrafi ogni M, a partire da un certo paragrafo.
Il file è organizzato in paragrafi nel senso che ci sono solo blocchi di questo tipo:

Codice: Seleziona tutto

4200	1	0.48866737734880135981
4200	2	0.64377173420378979086
4200	3	0.72886552552414693548
4200	4	0.78399466507619085742
4200	5	0.82323357749014809887
4200	6	0.85230492437998953462
4200	7	0.87422612004577401234
4200	8	0.89042143017762747986
4200	9	0.90189414753199963827
4200	10	0.90949553234721089261
4200	11	0.9231822089173056748


intervallati proprio da una riga "vuota", dove per vuota si intende che contiene solo spazi, tab o newline.

Per risolvere questo problema, ho ragionato "escogitato" questo comando:

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~/Scrivania$ awk -v start=2545 -v lines=11 -v every=10 '{if (counter > 0) {print; --counter}} NR == start {print; counter=lines; start+=every*(lines+1)}' EstrazioneParagrafi.txt
In pratica uso la variabile NR per iniziare la stampa, indicando di quante linee è composto il paragrafo e ogni quanti paragrafi voglio prenderne uno.
(in questo caso ne stampo uno, ma si può ovviamente generalizzare questo procedimento per stamparne N)

Ho "escogitato" altri modi, ma tutti hanno gli ovvi inconvenienti che ha anche questo. Ovvero, devo sapere la riga da cui partire, di quante righe è composto un paragrafo... e via dicendo.

Pertanto... alternative?

Grazie in anticipo
:ciao:
Ultima modifica di vaeVictis il domenica 29 giugno 2014, 21:10, modificato 1 volta in totale.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

Ciao VaeVictis, non ho capito bene com'è fatto il file e nemmeno cosa vuoi fare.
Comunque, se devi estrarre righe intere
(dovresti fare in modo di avere le righe vuote veramente vuote cioè contenenti solo'\n')
potresti considerare i campi come singole righe e i record come paragrafi, in pratica una cosa di questo genere

Codice: Seleziona tutto

 BEGIN {
    FS="\n"
    RS="\n\n"
    OFS=FS
    ORS=RS
}
{istruzioni per estrazione}
Salva l'Ucraina! 🇺🇦
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

Ho riletto meglio! Devi estrarre gli interi blocchi! Puoi considerare il file come un unico record dove i blocchi sono i campi.

Con un file così:

Codice: Seleziona tutto

8-) cat file.txt
p1	foo	bar foobar
p1	foo	bar foobar
p1	foo	bar foobar

p2	foo	bar foobar
p2	foo	bar foobar
p2	foo	bar foobar
p2	foo	bar foobar

p3	foo	bar foobar
p3	foo	bar foobar

p4	foo	bar foobar
p4	foo	bar foobar
p4	foo	bar foobar

p5	foo	bar foobar
p5	foo	bar foobar
p5	foo	bar foobar

8-)
Estraggo gli interi blocchi 2 e 5

Codice: Seleziona tutto

8-) awk 'BEGIN {FS="\n\n";RS="\0";OFS=FS;ORS="\n\n"}{print $2,$5}' file.txt
p2	foo	bar foobar
p2	foo	bar foobar
p2	foo	bar foobar
p2	foo	bar foobar

p5	foo	bar foobar
p5	foo	bar foobar
p5	foo	bar foobar

8-) 
Salva l'Ucraina! 🇺🇦
Avatar utente
zdf_9
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 940
Iscrizione: venerdì 18 giugno 2010, 10:03
Distribuzione: debian x86_64

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da zdf_9 »

Penso questo risolva i tuo problema (da come l'ho intuito):

Codice: Seleziona tutto

awk -v INIZIO=5 -v STAMPARE=2 -v SKIP=1 'BEGIN {RS="\n\n";ORS="\n\n";PARAGRAFO=0.0;PARAGRAFO_IN=INIZIO;PARAGRAFO_FN=INIZIO+STAMPARE-1;} {PARAGRAFO++; if (PARAGRAFO >= PARAGRAFO_IN && PARAGRAFO <= PARAGRAFO_FN){print $0; if (PARAGRAFO==PARAGRAFO_FN) {PARAGRAFO_IN+=STAMPARE+SKIP; PARAGRAFO_FN+=STAMPARE+SKIP}} }' NOMEFILE
AWK sua le variabili INIZIO, STAMPARE e SKIP definite esternamente (in modo che puoi modificarle anche da script).
Sostituisci a NOMEFILE il nome del file da elaborare.

Non è il massimo dei codici, ma funziona.

EDIT.
L'awk che ho postato funziona solo con una riga vuota come delimitatore dei paragrafi.

Se vi sono più righe vuote si comporta in maniera "insapettata"
Non è considerata riga "vuota" una con uno o più spazi e/o tab.

Per risolvere questi altri problemi devo pensarci... forse facendo preprocessare il file.
il nemico più grande si nasconde nell'ultimo posto dove guardi
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

Ganzo!
Io avevo in mente un sistema un po diverso ma oggi non carburo e non ho neanche provato, ho il mal di cranio :ciao: .
Salva l'Ucraina! 🇺🇦
Avatar utente
zdf_9
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 940
Iscrizione: venerdì 18 giugno 2010, 10:03
Distribuzione: debian x86_64

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da zdf_9 »

Ho trovato la soluzione:

Codice: Seleziona tutto

awk -v INIZIO=5 -v STAMPARE=2 -v SKIP=1 'BEGIN {RS="\n[ \t\n]*\n";ORS="\n\n";PARAGRAFO=0.0;PARAGRAFO_IN=INIZIO;PARAGRAFO_FN=INIZIO+STAMPARE-1;} {PARAGRAFO++; if (PARAGRAFO >= PARAGRAFO_IN && PARAGRAFO <= PARAGRAFO_FN){print $0; if (PARAGRAFO==PARAGRAFO_FN) {PARAGRAFO_IN+=STAMPARE+SKIP; PARAGRAFO_FN+=STAMPARE+SKIP}} }' NOMEFILE
In pratica RS="\n[ \t\n]*\n" al posto di RS="\n\n".
il nemico più grande si nasconde nell'ultimo posto dove guardi
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

Giusto!
Dovrebbe fungere anche:

Codice: Seleziona tutto

RS="\n[\s]*\n"
Salva l'Ucraina! 🇺🇦
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da vaeVictis »

Grazie per l'interessamento e la decrittazione delle informazioni che, evidentemente, non avevo dato in modo chiaro.
Ad occhio e croce penso che ci abbiate preso, ma al momento non posso verificare.
Appena ho modo, me ne accerto. Controllando anche queste variabili che proprio non conoscevo :)

p.s.:
Le righe *vuote* che ho indicato come potenzialmente composte di spazi tab e newline, contengono in realtà solo il newline.
Nel senso che sono vuote 'per davvero'.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
zdf_9
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 940
Iscrizione: venerdì 18 giugno 2010, 10:03
Distribuzione: debian x86_64

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da zdf_9 »

Figurati... ;)

Una precisazione sull'ultimo AWK che ho postato.
Se hai più righe bianche (anche con spazi e/o tab) vengono tutte prese come UNICO separatore di paragrafi.
Alla fine dell'ultimo paragrafo estrapolato viene immessa una riga vuota.
il nemico più grande si nasconde nell'ultimo posto dove guardi
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

@VaeVictis: Non sei tu che non sei stato chiaro sono io che non fungo bene, (sinusite a palla e cervello cotto).
Fortunatamente è intervenuto zdf_9 .
Salva l'Ucraina! 🇺🇦
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da vaeVictis »

Allora, sto facendo le prove e noto che c'è qualcosa (che credo di saper risolvere) che non va nella gestione dello SKIP

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~/Programmazione/Bash/Awk/EstrazioneParagrafi$ awk -v INIZIO=1 -v STAMPARE=1 -v SKIP=10 'BEGIN {RS="\n[ \t\n]*\n";ORS="\n\n";PARAGRAFO=0.0;PARAGRAFO_IN=INIZIO;PARAGRAFO_FN=INIZIO+STAMPARE-1;} {PARAGRAFO++; if (PARAGRAFO >= PARAGRAFO_IN && PARAGRAFO <= PARAGRAFO_FN){print $0; if (PARAGRAFO==PARAGRAFO_FN) {PARAGRAFO_IN+=STAMPARE+SKIP; PARAGRAFO_FN+=STAMPARE+SKIP}} }' FileConParagrafi.txt 
1	foo-1-1	bar-1-1
1	foo-1-2	bar-1-2

12	foo-12-1	bar-12-1

23	foo-23-1	bar-23-1
23	foo-23-2	bar-23-2

34	foo-34-1	bar-34-1
34	foo-34-2	bar-34-2
34	foo-34-3	bar-34-3
34	foo-34-4	bar-34-4
34	foo-34-5	bar-34-5

45	foo-45-1	bar-45-1
45	foo-45-2	bar-45-2
45	foo-45-3	bar-45-3
45	foo-45-4	bar-45-4
45	foo-45-5	bar-45-5
45	foo-45-6	bar-45-6

Ora vedo di risolvere (non vi ci "dannate", credo di aver capito da cosa dipende) e poi vi spiego perché è nata l'esigenza di fare questa cosa e come ho *customizzato* il vostro consiglio.
:)
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
zdf_9
Scoppiettante Seguace
Scoppiettante Seguace
Messaggi: 940
Iscrizione: venerdì 18 giugno 2010, 10:03
Distribuzione: debian x86_64

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da zdf_9 »

Ho sbagiato ad assegnare il nome alla variabile SKIP. Sarebbe stato meglio chiamarla NOSTAMP (paragrafi da non stampare).
Per aggiustare lo script dovrebbe bastare modificare gli incrementi finali così:

Codice: Seleziona tutto

{PARAGRAFO_IN+=SKIP; PARAGRAFO_FN+=SKIP}
il nemico più grande si nasconde nell'ultimo posto dove guardi
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [awk] Stampa di N paragrafi ogni M

Messaggio da vaeVictis »

Concludendo...

L'esigenza di questo comando è nata perché sto facendo dei bellissimi grafici tridimensionali di alcuni dataset.
Questi file di dati arrivano ad essere composti da un numero inverosimilmente elevato di punti... roba di milioni di righe.
Quando lo passo a LaTeX (o, meglio, quando lo faccio elaborare dal pacchetto Pgfplots) vedo il warning "A soreta!"

Ho pertanto pensato di cogliere due piccione con una fava. Riduco il numero di dati ma non lo faccio in modo "uniforme".
Per questa estrazione, mi serve l'estrazione di un numero N di questi blocchi, ogni M.
Dal momento che questa estrazione è meglio che non sia uniforme (nel senso che in alcuni punti del file originale intensifico e in altri dirado il numero di record estratti), mi serve poter impostare uno start e uno stop.

Supponendo di avere un file di *righe normali* e di voler fare l'estrazione di 2 righe ogni 5, fino alla 15 (esclusa)... ovvero di voler estrarre le righe 1,2,6,7,11,12 si può fare una cosa del genere:

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~/Programmazione/Bash/Awk/EstrazioneParagrafi$ awk -v start=1 -v lines=2 -v every=5 -v stop=15 '{if (counter > 0) {print; --counter}} NR>=stop {exit}  NR == start {print; counter=lines-1; start+=every}' FileRigheNormali.txt 
riga-1
riga-2
riga-6
riga-7
riga-11
riga-12
Stavo morendo su come far rimanere awk di stucco, con un mega barbatrucco... poi siete arrivati voi e mi avete mostrato la via di RS.
Usando questa fantastica variabile, si può tranquillamente "estendere" il precedente comando con il BEGIN che mi avete suggerito:

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~/Programmazione/Bash/Awk/EstrazioneParagrafi$ awk -v start=1 -v lines=2 -v every=5 -v stop=15 'BEGIN {RS="\n[ \t\n]*\n";ORS="\n\n"}  {if (counter > 0) {print; --counter}} NR>=stop {exit}  NR == start {print; counter=lines-1; start+=every}' FileParagrafi.txt 
1	foo-1-1	bar-1-1
1	foo-1-2	bar-1-2

2	foo-2-1	bar-2-1
2	foo-2-2	bar-2-2
2	foo-2-3	bar-2-3
2	foo-2-4	bar-2-4

6	foo-6-1	bar-6-1
6	foo-6-2	bar-6-2
6	foo-6-3	bar-6-3
6	foo-6-4	bar-6-4

7	foo-7-1	bar-7-1
7	foo-7-2	bar-7-2
7	foo-7-3	bar-7-3
7	foo-7-4	bar-7-4
7	foo-7-5	bar-7-5
7	foo-7-6	bar-7-6

11	foo-11-1	bar-11-1
11	foo-11-2	bar-11-2
11	foo-11-3	bar-11-3

12	foo-12-1	bar-12-1

Cambiando RS, awk vede un blocco come singolo record... e NR non indica più le righe normali... ma il blocco intero.

Standing ovation per il programmatore che ha pensato ad RS.
Standing ovation per voi che me l'avete presentata!!

Alla prossima e grazie di cuore!

p.s.:
c'è la magagna legata al fatto che se non si passa lo "stop" awk si ferma subito, ma si risolve facile:

Codice: Seleziona tutto

vaevictis@vaevictis-HAL:~/Programmazione/Bash/Awk/EstrazioneParagrafi$ awk -v start=1 -v lines=2 -v every=5  '{if (counter > 0) {print; --counter}} stop && NR>=stop {exit}  NR == start {print; counter=lines-1; start+=every}' FileRigheNormali.txt 
riga-1
riga-2
riga-6
riga-7
riga-11
riga-12
riga-16
riga-17
riga-21
riga-22
riga-26
riga-27
riga-31
riga-32
riga-36
riga-37
riga-41
riga-42
riga-46
riga-47
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [Risolto] [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

Non conosco Pgfplots, poi lo cerco; in pratica cosa fai: diminuisci il numero di punti (xyz) che formano il reticolo 3D, giusto?
Esegui una specie di "Semplifica" oppure riduci la risoluzione in generale?

edit:
Ho dato un occhiata, in pratica fa quello che fa gnuplot ma per TeX.
Guardando gli esempi credo che tu usi la semplificazione, cioè se una curva può essere rappresentata perfettamente con tot punti te puoi ottenere la stessa curva (approssimata) con tot-n punti eliminando punti ad intervalli regolari eviti eventuali deformazioni.
È così?
Salva l'Ucraina! 🇺🇦
Avatar utente
vaeVictis
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4703
Iscrizione: venerdì 27 luglio 2012, 17:58
Desktop: Gnome
Distribuzione: Ubuntu 20.04 64bit

Re: [Risolto] [awk] Stampa di N paragrafi ogni M

Messaggio da vaeVictis »

UbuNuovo [url=http://forum.ubuntu-it.org/viewtopic.php?p=4608194#p4608194][img]http://forum.ubuntu-it.org/images/icons/icona-cita.gif[/img][/url] ha scritto:[...] in pratica cosa fai: diminuisci il numero di punti (xyz) che formano il reticolo 3D, giusto?
Esegui una specie di "Semplifica" oppure riduci la risoluzione in generale?
Il file di dati, che passi, in genere (almeno per quanto ho visto io), ad un programma di 'plotting', perché questo costruisca un grafico tridimensionale, è composto da blocchi analoghi a quello che ho inserito nel primo messaggio: tieni fissa una coordinata (in quel caso la X). vari la Yi sul suo range e di conseguenza avrai la terza colonna con le Z relative alla coppia (X,Yi).
La X nel mio caso è il 'tempo' e nelle simulazioni che ho fatto per produrre questi grafici faccio una misura ogni venti "secondi", su intervalli temporali complessivi che possono arrivare a qualche decina di milioni di secondi.
Pertanto, ho dei file con una cosa come (10milioni/20 = ) 500mila blocchi, ognuno strutturato come quello che ho postato.
Il programma non riesce a gestire questa mole di dati e crasha. A prescindere dal fatto che, se li gestisse, avrei comunque un'immagine di un grafico con un punto ogni 10^-5 metri (se ipotizziamo una larghezza di 15 cm per il grafico).
Dovrei dotare chi li legge di un visore futuristico che ancora sto sviluppando...
In attesa di averlo sviluppato (perché comunque puoi impostare pgfplots per accettare un numero di punti "maggiore") sfoltisco il grafico il dataset.


edit:
Ho dato un occhiata, in pratica fa quello che fa gnuplot ma per TeX.
[...]
Ni.
Pgfplots si occupa di un singolo aspetto specifico (la creazione del grafico) tra tutto quello che puoi fare invece con Gnuplot, ma lo fa in modo esteticamente molto più accurato.
Pirates arrrrrrrrrrr awesome!!!
«I fear not the man who has practiced 10000 kicks once,
but I fear the man who has practiced one kick 10000 times.»
Avatar utente
UbuNuovo
Imperturbabile Insigne
Imperturbabile Insigne
Messaggi: 4457
Iscrizione: sabato 12 dicembre 2009, 20:58
Desktop: Mate
Distribuzione: Ubuntu Mate 22.04.1 LTS
Sesso: Maschile
Contatti:

Re: [Risolto] [awk] Stampa di N paragrafi ogni M

Messaggio da UbuNuovo »

interessante, grazie per la delucidazione
Salva l'Ucraina! 🇺🇦
Scrivi risposta

Ritorna a “Programmazione”

Chi c’è in linea

Visualizzano questa sezione: 0 utenti iscritti e 3 ospiti