Chỉnh sửa giá trị trong tệp txt bằng lệnh sed / awk / grep


9

Trong 5 năm, tôi sử dụng trạm thời tiết La Crosse WS2350. Dữ liệu được cung cấp bởi trạm thời tiết được xử lý với open2300 trên RPI. Điều này hoạt động rất tốt. Tuy nhiên, dữ liệu nhiệt độ là sai (cảm biến). Dữ liệu nhiệt độ thấp hơn 1 ° C.

Vì tôi không thể hiệu chỉnh cảm biến, tôi muốn thay đổi giá trị nhiệt độ từ tệp được trích xuất từ ​​trạm thời tiết.

Tệp văn bản này (current.txt) chứa:

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

Tôi muốn thêm +1 vào các giá trị "To", "Tomin", "Tomax" và ghi đè tệp văn bản với các giá trị chính xác.

Sau khi nhìn vào các lệnh sed và awk, tôi nhận ra rằng mình đã lỗi thời. Ai có thể hướng dẫn cho tôi? Cảm ơn

Biên tập :

Tôi đã quên một tệp khác: ws2308.log Cứ sau 15 phút, một dòng mới được thêm vào tệp 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 

Giá trị được sửa đổi là trường thứ 5 (-1,2 đầu tiên)

Cũng cần thiết là trên dòng cuối cùng, giá trị của nhiệt độ được tăng thêm 1 và ghi đè lên dòng cuối cùng với giá trị chính xác. Chỉ dòng cuối cùng sẽ được tính đến bởi chương trình php cho phép hiển thị kết quả trong biểu đồ.

Cảm ơn

Câu trả lời:


12

Đây là một biến thể AWK thành ngữ hơn một chút để xử lý current.txt( câu trả lời thứ hai của steve thậm chí còn thành ngữ hơn!):

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

Điều này tìm kiếm các dòng bắt đầu bằng To, theo sau là không có gì min, hoặc max, theo sau là khoảng trắng; đối với các dòng khớp, nó sẽ in trường thứ nhất và trường thứ hai, tăng dần, được phân tách bằng dấu tách trường đầu ra mặc định (dấu cách). Sau đó, nó bỏ qua dòng tiếp theo. Tất cả các dòng khác được in nguyên trạng ( 1là một phím tắt cho điều này trong AWK).

Lưu ý rằng việc ghi đè tệp bằng các giá trị mới có thể không phải là ý hay: bạn sẽ không biết liệu các giá trị đó có được sửa hay không ... Nếu bạn truy xuất tệp từ thiết bị mỗi lần thì điều đó không áp dụng.

Lý do tương tự cũng được áp dụng ws2308.log, vì vậy, hãy cứ xử lý toàn bộ nó mỗi lần:

$ 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

Nếu bạn chỉ muốn dòng cuối cùng:

$ 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

hoặc nếu bạn muốn tập tin chỉ thay đổi dòng cuối cùng :

$ 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

Đây là một giải pháp. Đối với bất kỳ dòng nào bắt đầu bằng "Tới", "Tomin" hoặc "Tomax" theo sau là khoảng trắng, hãy in trường đầu tiên và sau đó trường thứ hai tăng thêm 1. Nếu không, chỉ cần in toàn bộ dòng.

$ 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

Một cách tiếp cận khác, hơi đánh gôn .

$ 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
Đẹp (nên +1), nhưng bạn chỉ có thể thêm nó dưới dạng chỉnh sửa vào câu trả lời hiện có của mình!
Stephen Kitt

@Scott -itrên awkthêm một tệp bao gồm, đó không sedphải là -itùy chọn của.
Stephen Kitt

@StephenKitt: Ôi! Tôi biết rằng.
Scott

5

Một cách tiếp cận Perl:

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

-ilàm cho nó ghi đè lên tập tin gốc, vì vậy nó sẽ in ra không có gì, nó sẽ thay đổi tập tin trực tiếp.

Việc -athực hiện perlhành động như thế awk, chia đầu vào của nó trên whitesapce (hoặc bất cứ thứ gì khác được cung cấp bởi -F) vào mảng @F. Vì vậy, trường thứ hai sẽ là $F[1]do các mảng bắt đầu đếm ở 0. Do đó, tập lệnh sẽ thay thế trường thứ hai bằng chính nó tăng lên bởi một trên các dòng bắt đầu bằng To.


2

Điều này sẽ làm công việc:

  1. Đầu tiên sẽ đi qua tất cả các dòng
  2. Sau đó kiểm tra mục đầu tiên và kiểm tra xem nó có phù hợp với những gì bạn muốn không.
  3. Sau đó, nếu nó khớp, in nó và thêm +1 vào mục tiếp theo trong dòng
  4. Khác chỉ cần in nó và in các mục tiếp theo

    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
    

ĐẦU RA

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.