基于UNIX中的文件内容重命名文件

时间:2014-07-05 17:14:09

标签: unix awk file-rename batch-rename

我在文件中有模式QUARTERDATE和FILENAME。 两者都有一些价值,如下面所示。

我的要求是,我应该重命名文件,如FILENAME_QUARTERDATE。

我的文件(myfile.txt)如下:

        QUARTERDATE:    03/31/14 - 06/29/14
        FILENAME   :    LEAD
field1  field2
34567
20.0    5,678
20.0    5,678
20.0    5,678
20.0    5,678
20.0    5,678

我希望文件名为LEAD_201402.txt 文件中的日期范围是针对第2季度的,因此我将其作为201402。

提前感谢您的回复。

2 个答案:

答案 0 :(得分:1)

newname=$(awk '/QUARTERDATE/ { split($4, d, "/"); 
                               quarter=sprintf("%04d%02d", 2000+d[3], int((d[1]-1)/3)+1); }
               /FILENAME/ { fn = $3; print fn "_" quarter; exit; }' "$file")
mv "$file" "$newname"

答案 1 :(得分:0)

如何定义四分之一?

正如对主要问题的评论所指出的那样,问题尚未定义。

  

上一季度的QUARTERDATE行会出现哪些数据? Q1可以从上一年12月开始吗? Q2的结束日期可能是7月(或4月的Q1,或10月的Q3,或1月的Q4)?自从Q2的第一个日期是3月以来,需要了解这些替代方案。一个季度可能会提前开始并且同时结束(14周的季度)吗?

回应是:

  

Q2的季度将从4月的第一个星期一开始,到6月的最后一个星期日结束。

这引发了反响:

  

2014-03-31是星期一,但几乎不是4月的星期一。这主要意味着您对四分之一的定义尚不清楚。例如,明年,2015-03-30是星期一,但是4月的第一个星期一'是2015-04-06。 2015年3月的最后一个星期日是2015-03-29。那么2015-03-30至(2015)05周(星期一)的哪个季度属于哪个,为什么?如果您不知道(如何以及为何),我们无法可靠地为您提供帮助。

合理的工作假设

  • Y2K的教训已经被遗忘了(为什么今年使用两位数字,该死!)。
  • 宿舍运行整整数周。
  • 宿舍周一开始,周日结束。
  • 宿舍与日历宿舍保持一致,而不是一年四季都在漂流。 (91天有13个星期,一年有4个这样的季度,但是普通年度有一个额外的一天,闰年有两个额外的一天,这意味着你偶尔会得到一个14周的季度,以确保事情保持一致。)
  • 一季度第一次约会的日期将在1月1日,4月1日,7月1日或10月1日附近,但月份可能是12月,3月(如问题所示),6月或9月。
  • 一个季度的最后一个日期将在3月31日,即6月30日,9月30日,12月31日附近,但月份可能是4月,7月,10月或1月。
  • 通过在开始月份添加1个模12(1..12范围内的值,而不是0..11),您应该在日历季度中坚持一个月。
  • 通过将1模12(在1..12范围内的值再次减去)减去最后一个月,您应该在日历季度中坚持一个月。
  • 如果数据有效,则'开始+ 1'并且'结束 - 1'月份应该在同一季度。
  • 如果开始日期是12月(但这表明明年的第一季度),那么早期可能是一次性的。
  • 如果结束日期是1月份(但这表示上一年度的第4季度),结束年份可能是一个接一个。

更具弹性的代码

尽管有上述描述,但是尽管季度开始和结束日期的任何或所有特性都可以编写检测季度的代码。此代码从Barmar answer借了一点,但该算法对日历的变幻莫测以及季度开始和结束日期更具弹性。

#!/bin/sh

awk '/QUARTERDATE/ {
         split($2, b, "/")
         split($4, e, "/")
         if      (b[1] == 12) { q = 1; y = e[3] }
         else if (e[1] ==  1) { q = 4; y = b[3] }
         else
         {
             if (b[3] != e[3]) {
                 print "Year mismatch (" $2 " vs " $4 ") in file " FILENAME
                 exit 1
             }
             m = int((b[1] + e[1]) / 2)
             q = int((m - 1) / 3) + 1
             y = e[3]
         }
         quarter = sprintf("%.4d%.2d", y + 2000, q)
     }
     /FILENAME/ {
         print $3 "_" quarter
         # exit
     }' "$@"

m的计算将开始月加1加到结束月减一,然后将整数除以2。在已经处理过极端情况的情况下,这总是产生一个正确的季度的月份数。

与FILENAME相关联的exit前面的评论可让您更轻松地进行测试。在单独处理每个文件时,如在Barmar的示例中,exit是一个重要的优化。请注意,如果输入来自标准输入,则错误消息将提供空文件名。 (另外,我不确定如何将错误消息打印到标准错误而不是标准输出,除了print "message" > "/dev/stderr"print "message" > "/dev/fd/2"等平台特定技术。

鉴于此样本输入数据(2014Q1至2015Q2的6个季度的半合理开始和结束日期):

        QUARTERDATE:    12/30/13 - 03/30/14
        FILENAME   :    LEAD
        QUARTERDATE:    03/31/14 - 06/29/14
        FILENAME   :    LEAD
        QUARTERDATE:    06/30/14 - 09/28/14
        FILENAME   :    LEAD
        QUARTERDATE:    09/29/14 - 12/28/14
        FILENAME   :    LEAD
        QUARTERDATE:    12/29/14 - 03/29/15
        FILENAME   :    LEAD
        QUARTERDATE:    03/30/15 - 06/29/15
        FILENAME   :    LEAD

此脚本的输出为:

LEAD_201401
LEAD_201402
LEAD_201403
LEAD_201404
LEAD_201501
LEAD_201502

您可以在合理范围内处理季度的开始和结束日期,您仍然可以获得所需的输出。但始终要警惕日历计算;他们几乎总是比你想象的更难。