แก้ไขค่าในไฟล์ txt ด้วยคำสั่ง sed / awk / grep


9

เป็นเวลา 5 ปีที่ฉันใช้สถานีอากาศ La Crosse WS2350 ข้อมูลจากสถานีตรวจอากาศถูกประมวลผลด้วย open2300 บน RPI มันใช้งานได้ดีมาก อย่างไรก็ตามข้อมูลอุณหภูมิเป็นเท็จ (เซ็นเซอร์) ข้อมูลอุณหภูมิลดลง 1 ° C

เนื่องจากฉันไม่สามารถปรับเทียบเซ็นเซอร์ได้ฉันต้องการเปลี่ยนค่าอุณหภูมิจากไฟล์ที่แยกจากสถานีตรวจอากาศ

ไฟล์ข้อความนี้ (current.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 -2.4
Tomin -4.8
Tomax 37.4
TTomin 06:46
DTomin 2016-02-18
TTomax 16:13
DTomax 2016-07-19
...

ฉันต้องการเพิ่ม +1 ให้กับค่า "ถึง", "Tomin", "Tomax" และเขียนทับไฟล์ข้อความด้วยค่าที่ถูกต้อง

หลังจากดูคำสั่ง sed และ awk ฉันรู้ว่าฉันล้าสมัยแล้ว มีใครแนะนำฉันได้บ้าง ขอบคุณ

แก้ไข:

ฉันลืมไฟล์อื่น: ws2308.log ทุก ๆ 15 นาทีจะมีการเพิ่มบรรทัดใหม่ในไฟล์ 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 

ค่าที่จะแก้ไขคือฟิลด์ที่ 5 (-1.2 แรก)

นอกจากนี้ยังจำเป็นที่ในบรรทัดสุดท้ายค่าของอุณหภูมิจะเพิ่มขึ้น 1 และเขียนทับบรรทัดสุดท้ายด้วยค่าที่ถูกต้อง เฉพาะบรรทัดสุดท้ายเท่านั้นที่จะถูกนำมาพิจารณาโดยโปรแกรม php ซึ่งอนุญาตให้แสดงผลลัพธ์ในกราฟ

ขอบคุณ

คำตอบ:


12

นี่เป็น AWK ที่แตกต่างออกไปเล็กน้อยสำนวนมากขึ้นในกระบวนการcurrent.txt( คำตอบที่สองของสตีฟคือแม้สำนวนอื่น ๆ !):

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

สิ่งนี้จะค้นหาบรรทัดที่ขึ้นต้นด้วยToตามด้วยไม่มีอะไรminหรือmaxตามด้วยช่องว่าง สำหรับการจับคู่บรรทัดมันจะพิมพ์ฟิลด์แรกและฟิลด์ที่สองเพิ่มขึ้นคั่นด้วยตัวคั่นฟิลด์เอาต์พุตดีฟอลต์ (ช่องว่าง) จากนั้นจะข้ามไปยังบรรทัดถัดไป บรรทัดอื่นทั้งหมดจะถูกพิมพ์ตาม - เป็น ( 1เป็นทางลัดสำหรับสิ่งนี้ใน AWK)

โปรดทราบว่าการเขียนทับไฟล์ด้วยค่าใหม่อาจไม่ใช่ความคิดที่ดี: คุณจะไม่รู้ว่าค่านั้นได้รับการแก้ไขหรือไม่ ... หากคุณดึงไฟล์จากอุปกรณ์ทุกครั้ง

เหตุผลเดียวกันนี้นำไปใช้กับws2308.logดังนั้นเราจะดำเนินการให้ครบถ้วนทุกครั้ง:

$ 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

หากคุณต้องการเฉพาะบรรทัดสุดท้าย:

$ 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

หรือถ้าคุณต้องการไฟล์ที่มีการเปลี่ยนแปลงบรรทัดสุดท้ายเท่านั้น:

$ 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

นี่คือทางออกหนึ่ง สำหรับบรรทัดใด ๆ ที่ขึ้นต้นด้วย "ถึง", "Tomin" หรือ "Tomax" ตามด้วยช่องว่างให้พิมพ์เขตข้อมูลแรกแล้วเขตข้อมูลที่สองเพิ่มขึ้น 1 หรือมิฉะนั้นเพียงพิมพ์เต็มบรรทัด

$ 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

อีกวิธีหนึ่งเล็กน้อย แข็งแรงเล่นกอล์ฟ

$ 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
ดีมาก (ดังนั้น +1) แต่คุณสามารถเพิ่มได้ว่าเป็นการแก้ไขคำตอบที่คุณมีอยู่!
Stephen Kitt

@Scott -iบนawkเพิ่มรวมไฟล์ก็ไม่มีอะไรเหมือนsed's -iตัวเลือก
Stephen Kitt

@StephenKitt: D'oh! ฉันรู้ว่า.
สกอตต์

5

วิธีการ Perl:

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

-iทำให้มันเขียนทับไฟล์เดิมจึงจะพิมพ์อะไรก็จะเปลี่ยนไฟล์โดยตรง

-aทำให้perlการกระทำเช่นawkแยกปัจจัยการผลิตใน whitesapce (หรือสิ่งอื่นใดที่กำหนดโดย-F) @Fลงในอาร์เรย์ ดังนั้นข้อมูลที่สองจะเป็น$F[1]เพราะอาร์เรย์เริ่มนับที่ 0 Toสคริปต์จึงจะเข้ามาแทนที่ฟิลด์ที่สองกับตัวเองเพิ่มขึ้นโดยหนึ่งในสายที่เริ่มต้นด้วย


2

สิ่งนี้จะทำงาน:

  1. ก่อนจะผ่านทุกบรรทัด
  2. จากนั้นตรวจสอบรายการแรกและตรวจสอบว่ามันตรงกับสิ่งที่คุณต้องการ
  3. จากนั้นหากตรงกันให้พิมพ์และเพิ่ม +1 ในรายการถัดไปในบรรทัด
  4. อื่นเพียงพิมพ์และพิมพ์รายการถัดไป

    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
    

เอาท์พุท

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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.