Edytuj wartości w pliku txt za pomocą polecenia sed / awk / grep

9

Od 5 lat używam stacji pogodowej La Crosse WS2350. Dane dostarczone przez stację pogodową są przetwarzane za pomocą open2300 na RPI. To działa bardzo dobrze. Jednak dane temperatury są fałszywe (czujnik). Dane temperatury są o 1 ° C niższe.

Ponieważ nie mogę skalibrować czujnika, chcę zmienić wartość temperatury z pliku pobranego ze stacji pogodowej.

Ten plik tekstowy (current.txt) zawiera:

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
...

Chcę dodać +1 do wartości „Do”, „Tomin”, „Tomax” i zastąpić plik tekstowy prawidłowymi wartościami.

Po przejrzeniu poleceń sed i awk zdaję sobie sprawę, że jestem przestarzały. Czy ktoś może mnie poprowadzić? Dzięki

Edytować :

Zapomniałem innego pliku: ws2308.log Co 15 minut do pliku ws2308.log dodawany jest nowy wiersz:

...
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 

Wartość do modyfikacji to piąte pole (pierwsze -1,2)

Konieczne jest również, aby w ostatnim wierszu wartość temperatury była zwiększana o 1 i zastępowała ostatnią linię prawidłową wartością. Program php bierze pod uwagę tylko ostatni wiersz, który pozwala wyświetlić wyniki na wykresie.

Dzięki

Ookpik
źródło

Odpowiedzi:

12

Oto nieco bardziej idiomatyczny wariant AWK do przetworzenia current.txt( druga odpowiedź Steve'a jest jeszcze bardziej idiomatyczna!):

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

Szuka linii zaczynających się od To, po których nie ma nic min, lub max, po których następuje spacja; dla pasujących linii wypisuje pierwsze pole i drugie pole, przyrostowe, oddzielone domyślnym separatorem pól wyjściowych (spacją). Następnie przeskakuje do następnej linii. Wszystkie pozostałe wiersze są drukowane w obecnej postaci ( 1jest to skrót do tego w AWK).

Pamiętaj, że nadpisanie pliku nowymi wartościami prawdopodobnie nie jest dobrym pomysłem: nie będziesz wiedział, czy wartości zostały poprawione, czy nie ... Jeśli za każdym razem pobierzesz plik z urządzenia, nie ma to zastosowania.

Dotyczy to ws2308.logtego samego rozumowania , dlatego za każdym razem przetwarzajmy go w całości:

$ 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

Jeśli chcesz tylko ostatni wiersz:

$ 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

lub jeśli chcesz zmienić plik z ostatnią linią :

$ 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
Stephen Kitt
źródło
10

Oto jedno rozwiązanie. W przypadku wszystkich wierszy zaczynających się od „Do”, „Tomin” lub „Tomax”, po których następuje spacja, wydrukuj pierwsze pole, a następnie drugie pole z przyrostem o 1. W przeciwnym razie po prostu wydrukuj pełną linię.

$ 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
$
Steve
źródło
5

Inne podejście, lekko golfa .

$ 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
$
Steve
źródło
3
Fajnie (więc +1), ale mogłeś dodać to jako edycję do swojej istniejącej odpowiedzi!
Stephen Kitt,
@Scott -ina awkDodaje to plik, to nic takiego sed„s -iopcja.
Stephen Kitt
@StephenKitt: D'oh! Wiedziałem to.
Scott
5

Podejście Perla:

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

-iCzyni go zastąpić oryginalny plik, więc będzie wydrukować nic, będzie to zmienić plik bezpośrednio.

W -amarki perldziałają jak awk, podział jego wejście na whitesapce (lub coś jeszcze wydane przez -F) w tablicy @F. Tak więc drugie pole będzie miało miejsce, $F[1]ponieważ tablice zaczynają odliczać od 0. Skrypt zastąpi zatem drugie pole, zwiększając je o jeden w wierszach zaczynających się od To.

terdon
źródło
2

To wykona pracę:

  1. Najpierw przejdzie wszystkie linie
  2. Następnie sprawdź pierwszy element i sprawdź, czy pasuje do tego, co chcesz.
  3. Następnie, jeśli pasuje, wydrukuj go i dodaj +1 do następnego elementu w wierszu
  4. W przeciwnym razie po prostu go wydrukuj i wydrukuj następny element

    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
    

WYNIK

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
Wissam Roujoulah
źródło