Awk 在文本文件中修改日期格式

Awk 在文本文件中修改日期格式,awk,Awk,我有一些包含以下行的文本文件: 07JAN01,-0.24727942769082E+07,-0.467133797284279E+07,0.3558107777473149E+07 07JAN02,-0.247297942405032E+07,-0.467133797586388E+07,0.3558107777517715E+07 03年1月7日,-0.247297942584851E+07,-0.46713379772722E+07,0.3558107777627353E+07 我需要

我有一些包含以下行的文本文件:

07JAN01,-0.24727942769082E+07,-0.467133797284279E+07,0.3558107777473149E+07

07JAN02,-0.247297942405032E+07,-0.467133797586388E+07,0.3558107777517715E+07

03年1月7日,-0.247297942584851E+07,-0.46713379772722E+07,0.3558107777627353E+07

我需要制作一份脚本,将日期格式修改为:

01/01/07,-0.24727942769082E+07,-0.467133797284279E+07,0.3558107777473149E+07

02/01/07,-0.247297942405032E+07,-0.467133797586388E+07,0.3558107777517715E+07

03/01/07,-0.247297942584851E+07,-0.467133797727224E+07,0.3558107777627353E+07

我正在寻找一个合适的sed或grep命令,以便只提取每行的一些字符,将其定义为脚本中的变量。由于我想“重组”日期,我考虑定义三个变量,其中第一行的变量为:

a=07

b=JAN(我认为需要在脚本中实现一个“case”来处理这个问题?)

c=03

我查看了一些grep示例和大量文档,但没有真正清晰的内容出现。。。 找到了一些关于-cut命令的信息,但是。。。我不太确定这是否合适

我的另一个问题是关于输出,因为sed不修改输入数据,如何直接修改文件?有办法吗


非常感谢您的帮助:)

有点笨重,但您可以:

sed -e 's/^\(..\)JAN\(..\)/\2\/01\/\1/'
sed -e 's/^\(..\)FEB\(..\)/\2\/02\/\1/'
...
要就地运行sed,请参阅
-i
命令行选项:

sed -i -e ...
编辑


我想指出的是,这回答了之前没有指定AWK的问题。

我认为grep不是适合这份工作的工具。您需要一些更具表现力的东西,如Perl或awk:

echo '07JAN01, -0.24729E+07, -0.46713E+07, 0.35581E+07
      07JAN02, -0.24729E+07, -0.46713E+07, 0.35581E+07
      07AUG03, -0.24729E+07, -0.46713E+07, 0.35581E+07' | awk -F, '
{
    yy=substr($1,1,2);
    mm=substr($1,3,3);
    mm=(index(":JAN:FEB:MAR:APR:MAY:JUN:JUL:AUG:SEP:OCT:NOV:DEC",mm)+2)/4;
    dd=substr($1,6,2);
    printf "%02d/%02d/%02d,%s,%s,%s\n",dd,mm,yy,$2,$3,$4
}'
由此产生:

01/01/07, -0.24729E+07, -0.46713E+07, 0.35581E+07
02/01/07, -0.24729E+07, -0.46713E+07, 0.35581E+07
03/08/07, -0.24729E+07, -0.46713E+07, 0.35581E+07
很明显,这只是通过命令行awk脚本泵送一些测试数据。您最好将其放入实际的awk脚本文件中,并通过它运行您的输入

如果datchg.awk包含:

{
    yy=substr($1,1,2);
    mm=substr($1,3,3);
    mm=(index(":JAN:FEB:MAR:APR:MAY:JUN:JUL:AUG:SEP:OCT:NOV:DEC",mm)+2)/4;
    dd=substr($1,6,2);
    printf "%02d/%02d/%02d,%s,%s,%s\n",dd,mm,yy,$2,$3,$4
}
然后:

还生产:

01/01/07, -0.24729E+07, -0.46713E+07, 0.35581E+07
02/01/07, -0.24729E+07, -0.46713E+07, 0.35581E+07
03/08/07, -0.24729E+07, -0.46713E+07, 0.35581E+07
其工作原理如下。每一行都被拆分为字段(
-F,
将字段分隔符设置为逗号),我们提取并处理字段1(日期)的相关部分。我的意思是,通过搜索字符串并操作找到它的索引,年份和日期被颠倒,文本月份被转换为数字月份,因此它在1到12之间

这是唯一(相对)棘手的一点,是通过一些基本的数学运算完成的:index函数只需在您的月份字符串中查找位置(其中第一个字符是1)。因此,一月在位置2,二月在6,三月在10,…,十二月在46(集合{2,6,10,…,46})。它们相距4,所以我们需要除以4最终得到连续的月份数,但首先我们加2,这样除法会很好地工作。加上2就得到了集合{4,8,12,…,48}。然后你除以4得到{1,2,3,…12},这是你的月数:

Text   Pos   +2   /4
----   ---   --   --
JAN      2    4    1
FEB      6    8    2
MAR     10   12    3
APR     14   16    4
MAY     18   20    5
JUN     22   24    6
JUL     26   28    7
AUG     30   32    8
SEP     34   36    9
OCT     38   40   10
NOV     42   44   11
DEC     46   48   12
然后我们只输出新信息。显然,如果您提供的数据不好,这很可能会让人呕吐,但我假设:

  • 数据是好的;或
  • 您将添加自己的错误检查
关于直接修改文件,由来已久的UNIX传统是使用shell脚本将当前文件保存到其他位置,处理它以创建新文件,然后用新文件覆盖旧文件(但不要触及保存的文件,以防出现严重错误)

我不会再详细说明我的答案了,你可能已经睡着了:-)

awk'BEGIN{
OFS=FS=“,”
#创建月份到数字的映射表
s=拆分(“一月:二月:三月:四月:五月:六月:七月:八月:九月:十月:十一月:十二月”,d,“:”)

对于(o=1;oThanks!我来看看这个。我必须问一下——为什么投否决票?我说它很笨重,但写起来花了几秒钟,而且很有效。AWK的解决方案很好,但更复杂。呃,对不起,我没有真正理解投票的要点……我没有接受你的帖子作为最终答案,我想等一下。但我没有“投否决票”我认为是这样的。或者如果是这样的话,那不是故意的。因为这是解决问题的另一种方式,它很有帮助!我现在“投票”了它。:)Thx!它很笨重,因为你还执行了12次sed(每个月),使其效率低下。我想这就是它被否决的原因。阿克海伦:不,你做了正确的事情——你接受了最佳答案——除非你特别单击向下箭头,否则它不会被否决。幽灵狗74:当然它很笨重(就像我说的),但我确信实际性能差异可以忽略不计。非常感谢……我刚刚粘贴了代码,它工作得非常完美。现在我需要学习语法以了解它的工作原理;)尤其是:mm=(索引(“:一月:二月:三月:四月:五月:六月:七月:八月:九月:十月:十一月:十二月”,mm)+2)/4、 非常感谢,帕克斯!很高兴看到一些人仍然愿意帮助新手,给出精确而简洁的答案;)@Ackheron:索引只会在您的月份字符串中找到位置(第一个字符是1)因此,1月=2,2月=6,3月=10,…,12月=46。然后你加2得到4,8,12,…,48。然后你除以4得到1,2,3,…,12。请参阅更新。awk是最好的。将任何带有空格分隔字段的行输入导入awk;你可以使用$0,$1等单独访问每个字段。例如,cat myapachelog | awk'{print$10}'只显示在单个列中传输的字节,或cat myapachelog | awk'{total+=$10}END{print total}'输出从logfile@Pax:非常感谢您的更新,现在真的帮助我了解了它的工作原理!;)非常清楚。这很聪明!@Flubba:谢谢您的建议
Text   Pos   +2   /4
----   ---   --   --
JAN      2    4    1
FEB      6    8    2
MAR     10   12    3
APR     14   16    4
MAY     18   20    5
JUN     22   24    6
JUL     26   28    7
AUG     30   32    8
SEP     34   36    9
OCT     38   40   10
NOV     42   44   11
DEC     46   48   12
awk 'BEGIN{
    OFS=FS=","
    # create table of mapping of months to numbers
    s=split("JAN:FEB:MAR:APR:MAY:JUN:JUL:AUG:SEP:OCT:NOV:DEC",d,":")
    for(o=1;o<=s;o++){
        m=sprintf("%02s",o)   # add 0 is single digit    
        date[d[o]]=m
    }
}
{
    yr=substr($1,1,2)
    mth=substr($1,3,3)
    day=substr($1,6,2)
    $1=day"/"date[mth]"/"yr    
}1' file