爱气象,爱气象家园! 

气象家园

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博登陆

只需一步, 快速开始

搜索
查看: 8585|回复: 11

[经验总结] 气象数据处理脚本篇(二):批处理

[复制链接]

新浪微博达人勋

发表于 2012-6-17 12:43:32 | 显示全部楼层 |阅读模式

登录后查看更多精彩内容~

您需要 登录 才可以下载或查看,没有帐号?立即注册 新浪微博登陆

x
本帖最后由 雪花纷飞 于 2012-6-17 13:00 编辑

       接着上一篇的问题继续讨论,现有2011年全年数据,要求提取2011年全年数据中date和uwind两列,并按时间顺序放入同一文件uwind_2011.txt中。数据格式如下图所示:
2.JPG


中心思想:要想实现对数据批处理,关键在于对文件名做文章。

思路1:如果提供的数据名很有规律,如以上文件名wind_yyyy-mm-dd.txt,很自然的想到用三个变量分别代表year、month和day。然后用一个三重循环就可以搞定了。不过由于一个月天数可能是30 or 31天(二月份是28 or 29天),需要判断比较麻烦。

  1. #! /bin/bash
  2. for year in 2011
  3. do
  4.    for month in $(seq -w 1 12)
  5.    do
  6.      case $month in
  7.        01|03|05|07|08|10|12)
  8.           for day in $(seq -w 1 31)
  9.           do
  10.              filename=wind_$year-$month-$day.txt
  11.             sed '1,7d' $filename | awk '{print $2,$3} >>uwind_2011.txt      
  12.           done
  13.           ;;
  14.        04|06|09|11)
  15.           for day in $(seq -w 1 30)
  16.           do
  17.              filename=wind_$year-$month-$day.txt
  18.              sed '1,7d' $filename | awk '{print $2,$3} >>uwind_2011.txt      
  19.           done
  20.           ;;
  21.        02)
  22.           for day in $(seq -w 1 28)
  23.           do
  24.              filename=wind_$year-$month-$day.txt
  25.              sed '1,7d' $filename | awk '{print $2,$3} >>uwind_2011.txt      
  26.           done
  27.           ;;
  28.       esac
  29.     done
  30. done
复制代码

        解释:外两层for语句是对year和month循环,seq -w 1 12语句保证输出一个01,02,…,12月份顺序序列。case语句类似于C语言中的switch case结构,判断每月有多少天。其中2月份没有讨论闰年还是平年(因为已经知道2011是平年了,但可以加上判断语句)。最内层对day循环,给文件名赋值,处理数据,注意这里用的是追加符>>使得数据保存在同一文件里。
        这个方法适用于有规律日期作为文件名的数据,以上例子恰好举了一年时间,如果是2011-3-15到2012-9-17的数据,只需在最内层循环加上判断语句即可。



思路2:对于以日期为文件名的文件,我们可以借助linux中date命令来解决问题。

首先简单介绍下date语法,详细介绍google或man date。
常用格式:date [-d datestr] [+ displayFormat]
选项含义:-d  datestr             显示由datestr描述的日期
                     +  displayFormat  控制日期输出格式
常用时间标记:
                      %Y    完整年份(如2012)
                      %y    年份后两位数字(如89)
                      %m   月份 (01..12)
                      %d   日(01..31)
                      % s   从1970年1月1日00:00:00到目前经历的秒数


  1. #! /bin/bash
  2. #start&end date formate should be yyyymmdd
  3. start_date=20110101
  4. end_date=20111231

  5. #transfer date into seconds and count num of days between s&e
  6. start_date_insec=$(date -d "$start_date" +%s)
  7. end_date_insec=$(date -d "$end_date" +%s)count_day=$[($end_date_insec-$start_date_insec)/(24*3600)+1]

  8. for((i=1;i<$count_day;i++))
  9. do
  10.     dt=$(date +%Y-%m-%d  -d "$start_date +$i days")
  11.     filename=wind_$dt.txt
  12.     sed  '1,7d'  $filename | awk '{print $2,$3} >>uwind_2011.txt
  13. done
复制代码

       解释:这里利用了date命令中设置指定日期向后N天的技巧,  date -d "$KNOW_DATE  +N days" +%Y%m%d。
                 首先将开始日期和截止日期转换成从1970年1月1日00:00:00到目前时间的秒数。两者相减除以一天时间的秒数再加1就是要处理的天数。这样转换可以忽略平年和闰年、每月天数的区别。比第一种方法更具有一般性。

思路3:通过ls列出数据所在目录下所有文件名(该目录最好只放置要处理的数据),将ls输出结果写入到一个文件中,将文件名赋给for循环中一个变量,实现循环处理。


  1. #! /bin/bash
  2. #脚本与数据data放在同级目录下
  3. ls ./data/*.txt  > ./data/filename.txt
  4. for fname in $(cat ./data/filename.txt)
  5. do
  6.    sed  '1,7d'  $fname | awk '{print $2,$3}' >> uwind_2011.txt
  7. done
复制代码

      解释:此方法更具一般性,不需要文件名按一定规则写,也不关心文件名是用英文还是中文,有没有规律。在英文Linux环境下,中文文件名会变成乱码,无法在脚本中输入中文名进行处理。而此方法则可用于中文文件名数据,如"海浪数据001.txt"这样的数据。
        上面说并不关心文件名有没有规律,针对本例处理要求还是需要ls输出文件名是按时间顺序排列的。实际上ls列出数据目录下文件顺序确实是以时间顺序排列的,这可以通过查看filename.txt验证。

        以上通过三种方法对txt文件进行了批处理,中心思想是实现对文件名的循环处理。而且越往下的方法越具有一般性。这两篇都是对txt文件的处理,下一篇则讨论下CSV文件处理的特殊要求




评分

参与人数 3金钱 +35 贡献 +13 收起 理由
topmad + 10 + 4
做个霸气的木头 + 10 + 4 赞一个!
mofangbao + 15 + 5

查看全部评分

密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-6-17 13:40:09 | 显示全部楼层
一般而言有规律的文件名比较多啦,你的更具通用性~谢楼主了,抢个沙发!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-9-4 15:00:50 | 显示全部楼层
牛啊!太好了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2012-9-19 11:22:50 来自手机 | 显示全部楼层
很好,很强大!date命令是脚本中对时间做计算最实用的命令!
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2015-4-13 16:58:42 | 显示全部楼层
学习了,太谢谢了
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2015-4-14 09:43:47 | 显示全部楼层
谢谢分享~~~~~~~~~~~~~~~~
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2015-4-14 11:15:38 | 显示全部楼层
第二次再看,又获益匪浅
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2015-4-14 15:50:39 | 显示全部楼层
谢谢分享     
密码修改失败请联系微信:mofangbao

新浪微博达人勋

发表于 2015-12-30 22:08:24 | 显示全部楼层
好帖{:eb502:}{:eb502:}{:eb502:}
密码修改失败请联系微信:mofangbao
回复

使用道具 举报

新浪微博达人勋

发表于 2016-3-9 09:58:15 | 显示全部楼层
谢谢楼主分享~~
密码修改失败请联系微信:mofangbao
您需要登录后才可以回帖 登录 | 立即注册 新浪微博登陆

本版积分规则

Copyright ©2011-2014 bbs.06climate.com All Rights Reserved.  Powered by Discuz! (京ICP-10201084)

本站信息均由会员发表,不代表气象家园立场,禁止在本站发表与国家法律相抵触言论

快速回复 返回顶部 返回列表