Modifica i valori in un file txt con il comando sed / awk / grep


9

Per 5 anni uso una stazione meteorologica La Crosse WS2350. I dati forniti dalla stazione meteorologica vengono elaborati con open2300 su RPI. Funziona molto bene Tuttavia, i dati di temperatura sono falsi (sensore). I dati di temperatura sono inferiori di 1 ° C.

Dal momento che non riesco a calibrare il sensore, voglio cambiare il valore della temperatura dal file estratto dalla stazione meteorologica.

Questo file di testo (current.txt) contiene:

Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -2.4
Tomin -4.8
Tomax 37.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
...

Voglio aggiungere +1 ai valori "A", "Tomin", "Tomax" e sovrascrivere il file di testo con i valori corretti.

Dopo aver esaminato i comandi sed e awk, mi rendo conto di essere obsoleto. Qualcuno può guidarmi? Grazie

Modificare :

Ho dimenticato un altro file: ws2308.log Ogni 15 minuti viene aggiunta una nuova riga al file ws2308.log:

...
20161203150600 2016-Dec-03 15:06:00 11.8 -1.1 -3.2 65 87 0.0 157.5 SSE -1.1 569.80 1015.700 
20161203152100 2016-Dec-03 15:21:00 12.3 -1.1 -3.2 64 87 0.0 157.5 SSE -1.1 569.80 1015.600 
20161203153600 2016-Dec-03 15:36:00 12.2 -1.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700 

Il valore da modificare è il 5 ° campo (il primo -1,2)

È inoltre necessario che sull'ultima riga, il valore della temperatura sia incrementato di 1 e sovrascriva l'ultima riga con il valore corretto. Solo l'ultima riga verrà presa in considerazione dal programma php che consente di visualizzare i risultati in un grafico.

Grazie

Risposte:


12

Ecco una variante AWK leggermente più idiomatica da elaborare current.txt( la seconda risposta di Steve è ancora più idiomatica!):

awk '/^To(|min|max) / { print $1, $2 + 1; next } 1' current.txt

Questo cerca le linee che iniziano con To, seguite da niente min, oppure maxseguite da uno spazio; per le linee corrispondenti stampa il primo campo e il secondo campo, incrementati, separati dal separatore del campo di output predefinito (spazio). Quindi passa alla riga successiva. Tutte le altre linee sono stampate così come sono ( 1è una scorciatoia per questo in AWK).

Si noti che sovrascrivere il file con i nuovi valori non è probabilmente una buona idea: non si saprà se i valori sono stati corretti o meno ... Se si recupera il file dal dispositivo ogni volta, ciò non si applica.

Lo stesso ragionamento si applica a ws2308.log, quindi cerchiamo di elaborarlo nella sua interezza ogni volta:

$ awk 'NF >= 5 { $5 = $5 + 1 } 1' ws2308.log
20161203150600 2016-Dec-03 15:06:00 11.8 -0.1 -3.2 65 87 0.0 157.5 SSE -1.1 569.80 1015.700
20161203152100 2016-Dec-03 15:21:00 12.3 -0.1 -3.2 64 87 0.0 157.5 SSE -1.1 569.80 1015.600
20161203153600 2016-Dec-03 15:36:00 12.2 -0.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700

Se vuoi solo l'ultima riga:

$ awk 'NF >= 5 { $5 = $5 + 1; lastline = $0 } END { print lastline }' ws2308.log
20161203153600 2016-Dec-03 15:36:00 12.2 -0.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700

o se si desidera che il file venga modificato solo con l'ultima riga :

$ awk 'length(prevline) > 0 { print prevline } NF >= 5 { prevline = $0; $5 = $5 + 1; lastline = $0 } END { print lastline }' ws2308.log
20161203150600 2016-Dec-03 15:06:00 11.8 -1.1 -3.2 65 87 0.0 157.5 SSE -1.1 569.80 1015.700 
20161203152100 2016-Dec-03 15:21:00 12.3 -1.1 -3.2 64 87 0.0 157.5 SSE -1.1 569.80 1015.600 
20161203153600 2016-Dec-03 15:36:00 12.2 -0.2 -3.3 64 87 0.0 135.0 SE -1.2 569.80 1015.700

10

Ecco una soluzione. Per ogni riga che inizia con "A", "Tomin" o "Tomax" seguita da uno spazio, stampa il primo campo e poi il secondo campo incrementato di 1. Altrimenti, stampa solo la linea intera.

$ awk '{if(/^(To|Tomin|Tomax) /){print $1 " " $2+1}else{print $0}}' w.txt
Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -1.4
Tomin -3.8
Tomax 38.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
$

5

Un altro approccio, leggermente golfato .

$ awk '/^To/{$2++}1' w.txt
Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -1.4
Tomin -3.8
Tomax 38.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
$

3
Bello (quindi +1), ma avresti potuto semplicemente aggiungerlo come modifica alla tua risposta esistente!
Stephen Kitt,

@Scott -ion awkaggiunge un file include, non è come sedl' -iopzione di.
Stephen Kitt,

@StephenKitt: D'oh! Sapevo che.
Scott,

5

Un approccio Perl:

perl -i -ape '/^To/ && s/$F[1]/$F[1]+1/e' file

Lo -ifa sovrascrivere il file originale, quindi non stamperà nulla, cambierà direttamente il file.

I -amarchi perlagiscono come awk, scissione suo ingresso whitesapce (o altro in -F) nella matrice @F. Quindi, il secondo campo sarà $F[1]perché le matrici iniziano a contare da 0. Lo script sostituirà quindi il secondo campo con se stesso incrementato di uno sulle righe che iniziano con To.


2

Questo farà il lavoro:

  1. In primo luogo passerà attraverso tutte le linee
  2. Quindi controlla il primo elemento e controlla se corrisponde a quello che desideri.
  3. Quindi, se corrisponde, stampalo e aggiungi +1 all'elemento successivo nella riga
  4. Altrimenti basta stamparlo e stampare l'elemento successivo

    awk '{
        for(i=1;i<=NF;i++) {
                t+=$i;if(i==1){
                        if($i=="To" ||$i=="Tomin" ||$i=="Tomax"  ){
                                printf  "%s ",$i;
                                print $(i+1)+1;}
    
                        else{
                                print $0
                                }
                        }
                        };
        }' current.txt
    

PRODUZIONE

Date 2016-Dec-03
Time 10:30:29
Ti 11.9
Timin 11.6
Timax 27.7
TTin 10:34
DTimin 2016-01-19
TTimax 00:44
DTimax 2016-08-28
To -1.4
Tomin -3.8
Tomax 38.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.