9

For 5 years, I use a weather station La Crosse WS2350. The data provided by the weather station are processed with open2300 on RPI. This works very well. However, the temperature data is false (sensor). The temperature data is 1 ° C lower.

Since I can not calibrate the sensor, I want to change the temperature value from the file extracted from the weather station.

This text file (current.txt) contains:

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

I want to add +1 to the values "To", "Tomin", "Tomax" and overwrite the text file with the correct values.

After looking at the sed and awk commands, I realize that I'm outdated. Can anyone guide me? Thanks

Edit :

I forgot another file: ws2308.log Every 15 minutes a new line is added to the 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 

The value to be modified is the 5th field (the first -1.2)

It is also necessary that on the last line, the value of the temperature is incremented by 1 and overwrite the last line with the correct value. Only the last line will be taken into account by the program php which allows to display the results in a graph.

Thanks

12

Here's a slightly more idiomatic AWK variant to process current.txt (steve's second answer is even more idiomatic!):

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

This looks for lines starting with To, followed by nothing, min, or max, followed by a space; for matching lines it prints the first field and the second field, incremented, separated by the default output field separator (space). Then it skips to the next line. All other lines are printed as-is (1 is a shortcut for this in AWK).

Note that overwriting the file with the new values is probably not a good idea: you won't know whether the values have been corrected or not... If you retrieve the file from the device every time then that doesn't apply.

The same reasoning applies to ws2308.log, so let's just process it in its entirety every time:

$ 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

If you want only the last line:

$ 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

or if you want the file with only the last line changed:

$ 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

Here's one solution. For any lines which start with "To", "Tomin" or "Tomax" followed by a space, print the first field and then the second field incremented by 1. Otherwise, just print the full line.

$ 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

Another approach, slightly golfed.

$ 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
    Nice (so +1), but you could just have added that as an edit to your existing answer! – Stephen Kitt Dec 3 '16 at 15:30
  • @Scott -i on awk adds an include file, it's nothing like sed's -i option. – Stephen Kitt Dec 13 '16 at 5:34
  • @StephenKitt: D'oh!  I knew that. – Scott Dec 13 '16 at 9:04
5

A Perl approach:

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

The -i makes it overwrite the original file, so it will print out nothing, it will change the file directly.

The -a makes perl act like awk, splitting its input on whitesapce (or anything else given by -F) into the array @F. So, the second field will be $F[1] because arrays start counting at 0. The script will therefore replace the second field with itself incremented by one on lines starting with To.

2

This will do the work:

  1. First will go through all lines
  2. Then check the first item and check if it matches what you want .
  3. Then, if it matches, print it and add +1 to the next item in the line
  4. Else just print it and print the next item

    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
    

OUTPUT

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.