Sed / awk / grep komutuyla bir txt dosyasındaki değerleri düzenleme


9

5 yıl boyunca La Crosse WS2350 hava istasyonu kullanıyorum. Hava istasyonu tarafından sağlanan veriler RPI'da open2300 ile işlenir. Bu çok iyi çalışıyor. Ancak, sıcaklık verileri yanlıştır (sensör). Sıcaklık verileri 1 ° C daha düşüktür.

Sensörü kalibre edemediğim için, hava istasyonundan çıkarılan dosyadan sıcaklık değerini değiştirmek istiyorum.

Bu metin dosyası (current.txt) şunları içerir:

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

"To", "Tomin", "Tomax" değerlerine +1 eklemek ve metin dosyasının üzerine doğru değerleri yazmak istiyorum.

Sed ve awk komutlarına baktıktan sonra, eskimiş olduğumu fark ettim. Biri bana rehberlik edebilir mi? Teşekkürler

Düzenle :

Başka bir dosya unuttum: ws2308.log Her 15 dakikada bir ws2308.log dosyasına yeni bir satır eklenir:

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

Değiştirilecek değer 5. alandır (ilk -1.2)

Son satırda, sıcaklığın değerinin 1 arttırılması ve son satırın üzerine doğru değerle yazılması gerekir. Sonuçların bir grafikte gösterilmesine izin veren program php tarafından sadece son satır dikkate alınacaktır.

Teşekkürler

Yanıtlar:


12

Burada işlemek için biraz daha deyimsel bir AWK varyantı var current.txt( steve'in ikinci cevabı daha da deyimsel!):

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

Bu , boşlukla başlayan To, ardından hiçbir şey minveya maxardından boşluk bırakılan satırları arar ; eşleşen çizgiler için, varsayılan çıkış alanı ayırıcısı (boşluk) ile ayrılmış olarak, birinci alanı ve ikinci alanı arttırır. Sonra bir sonraki satıra atlar. Diğer tüm satırlar olduğu gibi yazdırılır ( 1AWK'da bunun için bir kısayoldur).

Yeni değerlerle dosyanın üzerine yazmanın muhtemelen iyi bir fikir olmadığını unutmayın: değerlerin düzeltilip düzeltilmediğini bilemezsiniz ... Dosyayı her seferinde cihazdan alırsanız, bu geçerli olmaz.

Aynı akıl yürütme için de geçerlidir ws2308.log, bu yüzden her seferinde bütünüyle işleyelim:

$ 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

Yalnızca son satırı istiyorsanız:

$ 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

veya yalnızca son satırı içeren dosyanın değiştirilmesini istiyorsanız :

$ 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

İşte bir çözüm. "To", "Tomin" veya "Tomax" ile başlayan ve ardından boşluk bırakarak başlayan satırlar için önce ilk alanı sonra da 1 ile artan ikinci alanı yazdırın. Aksi takdirde, tüm satırı yazdırın.

$ 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

Başka bir yaklaşım, biraz golf .

$ 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
Güzel (yani +1), ancak bunu mevcut cevabınıza bir düzenleme olarak ekleyebilirdiniz!
Stephen Kitt

@Scott -ion awkbir içerme dosyası ekler, sed's -iseçenek gibi bir şey değildir .
Stephen Kitt

@StephenKitt: D'oh! Bunu biliyordum.
Scott

5

Bir Perl yaklaşımı:

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

-iO, orijinal dosyanın üzerine hiçbir şey yazdırmak böylece, bu dosyayı doğrudan değişecektir yapar.

-aMarkaları perlgibi hareket awkbölme, (başka tarafından verilen ya da bir şey whitesapce üzerindeki giriş -Fdiziye) @F. Dolayısıyla, ikinci alan $F[1]dizilerin 0'da saymaya başlamasıdır. Bu nedenle komut dosyası, ikinci alanı, kendisiyle başlayan satırlarda birer birer artan bir alanla değiştirir To.


2

Bu işi yapacak:

  1. İlk önce tüm satırlardan geçecek
  2. Ardından ilk öğeyi ve istediğiniz öğeyle eşleşip eşleşmediğini kontrol edin.
  3. Ardından, eşleşirse, yazdırın ve satırdaki bir sonraki öğeye +1 ekleyin
  4. Başka sadece yazdırın ve sonraki öğeyi yazdırın

    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
    

ÇIKTI

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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.