避免shell脚本中的while循环

9nvpjoqh  于 2023-08-07  发布在  Shell
关注(0)|答案(1)|浏览(93)

我有一个10分钟间隔的数据文件。但是,分钟和小时信息未正确写入。此外,小时需要增加3小时。
我的文件很长,有两年的数据。我的脚本通过while循环一行一行地阅读每一行。所以要花很多时间。我想避免while循环来快速执行它。

#!/bin/sh
#----------------------------
#INPUT FILE

#1st col: Year, 2nd: Month, 3rd: Day, 4th: hour, 5&6th: Value of A and B
cat << EOF > ifile.txt
17      01      01      00      3.3   -6.06
17      01      01      00      2.3   -7.8
17      01      01      00      3.13  -7.9
17      01      01      00      4.3   -8.0
17      01      01      00      4.4   -8.1
17      01      01      00      4.4   -8.1
17      01      01      00      1.8   -8.2
17      01      01      00      1.8   -8.2
17      01      01      00      6.3   -8.1
17      01      01      00      1.8   -8.2
17      01      01      00      1.8   -8.2
17      01      01      00      6.3   -8.1
17      01      01      00      1.2   -8.1
17      01      01      00      2.1   -8.0
17      01      01      00      2.0   -8.0
17      01      01      00      7.9   -8.0
EOF
#---------------------------------

# DESIRED OUTPUT

cat << EOF > ofile.txt
YY,MM,DD,HH,MIN,A,B,
17,01,01,03,00,3.3,-6.06,
17,01,01,03,10,2.3,-7.8,
17,01,01,03,20,3.13,-7.9,
17,01,01,03,30,4.3,-8.0,
17,01,01,03,40,4.4,-8.1,
17,01,01,03,50,4.4,-8.1,
17,01,01,04,00,1.8,-8.2,
17,01,01,04,10,1.8,-8.2,
17,01,01,04,20,6.3,-8.1,
17,01,01,04,30,1.8,-8.2,
17,01,01,04,40,1.8,-8.2,
17,01,01,04,50,6.3,-8.1,
17,01,01,05,00,1.2,-8.1,
17,01,01,05,10,2.1,-8.0,
17,01,01,05,20,2.0,-8.0,
17,01,01,05,30,7.9,-8.0,
EOF
#---------------------------------------

#My Script

cat << EOF > ofile.txt
YY,MM,DD,HH,MIN,A,B,
EOF

add_hr=3
add_min=00
n1=1
n2=$(wc -l < ifile.txt)
while [ $n1 -le $n2 ]
do

datetime="20170101 0000"
timestamp=$(date -d "$datetime" +%s)

new_timestamp=$((timestamp + add_hr * 3600 + add_min * 60))
new_datetime=$(date -d @$new_timestamp +"%Y%m%d%H%M")

DATE=$(echo "$new_datetime" | awk '{print substr($0,1,8)}')
YY=$(echo "${DATE}" | awk '{print substr($0,3,2)}')
MM=`date -d "${DATE}" "+%m"`
DD=`date -d "${DATE}" "+%d"`

HH=$(echo "$new_datetime" | awk '{print substr($0,9,2)}')
Min=$(echo "$new_datetime" | awk '{print substr($0,11,2)}')

A=$(awk 'NR=='$n1' {print $5}' ifile.txt)
B=$(awk 'NR=='$n1' {print $6}' ifile.txt)

cat << EOF >> ofile.txt
$YY,$MM,$DD,$HH,$Min,$A,$B,
EOF
add_min=$((add_min+10))
(( n1++ ))
done

字符串

v6ylcynt

v6ylcynt1#

GNU awk有strftime / mktime

gawk '
    BEGIN { print "YY,MM,DD,HH,MIN,A,B," }
    {
        fmt = "%y,%m,%d,%H,%M,"$5","$6","
        datespec = "20"$1" "$2" "$3" "($4+3)" "(min+0)" 0"
        print strftime(fmt, mktime(datespec,1), 1)
        min += 10
    }
' ifile.txt >ofile.txt

字符串
Perl解决方案也很短:

TZ=UTC perl -MPOSIX=strftime -aE '
    BEGIN { say "YY,MM,DD,HH,MIN,A,B," }
    say strftime "%y,%m,%d,%H,%M,$F[4],$F[5],",
        0, $min, $F[3]+3, $F[2], $F[1]-1, $F[0]+100;
    $min += 10
' ifile.txt >ofile.txt


Perl的-a选项自动将输入行分割为空白(类似于awk),并将分割的部分存储在数组@F中。
strftime参数为:fmtsecminhourmdaymonyear

mon从零开始(January = 0)。年份从1900年开始计算。

由于日期将与夏令时重叠,因此应将时区设置为不使用它们的区域设置。

相关问题