2015-05-06 200 views
0

我有一个条目,如大文件:删除逗号和格式的日期

<VAL>17,451.26</VAL> 
<VAL>353.93</VAL> 
<VAL>395.00</VAL> 
<VAL>2,405.00</VAL> 
<DATE>31 Jul 2013</DATE> 
<DATE>31 Jul 2013</DATE> 
<DATE>31 Dec 2014</DATE> 
<DATE>21 Jun 2002</DATE> 
<DATE>10 Jul 2002</DATE> 
<MOD>PL</MOD> 
<BATCH>13382</BATCH> 
<TYPE>Invoice</TYPE> 
<REF1>13541/13382</REF1> 
<REF2>671042638320</REF2> 
<NOTES>a-07 final elec</NOTES> 
<SNAME>EDF ENERGY (Electricity)</SNAME> 
<VAL>55.22</VAL> 
</CLT> 
<CLT> 
<CHD>MAT-01</CHD> 
<OPN>U5U1</OPN> 
<PERIOD>07 2013</PERIOD> 
<DATE>13 Jun 2013</DATE> 
<DATE>10 Jul 2002</DATE> 
<DATE>10 Jul 2002</DATE> 
<DATE>21 Aug 2007</DATE> 
<DATE>10 Jul 2002</DATE> 
<VAL>-4,122,322.03</VAL> 

我需要删除的VAL领域的逗号和更改日期YYYY-MM-DD(例如,2013年7月-31)在DATE字段中。

寻找快速(高效)的方法。

感谢

+0

'用VALUE字段替换逗号? – Jotne

+0

对不起,删除,而不是替换 – tozjerimiah

+0

看看strtotime()和替换() – Matheno

回答

1
sed '# init month convertor in holding buffer 
1{h;s/.*/Jan01Fev02Mar03Apr04May05Jun06Jul07Aug08Sep09Oct10Nov11Dec12/;x;} 

# change Val 
    /^<VAL>/ s/,//g 

# Change Date 
    /^<DATE>/ { 
# change month 
    G 
    s/[[:space:]]\{1,\}\([A-Z][a-z][a-z]\)[[:space:]]\{1,\}\(.*\)\n.*\1\([0-9][0-9]\).*/-\3-\2/ 
# reformat order 
    s/>\(.*\)-\(.*\)-\(.*\)</>\3-\2-\1</ 
    }' YourFile 
  • POSIX有没有额外的子外壳为DAE转换sed的
  • 格式化日起2 s///在这里,但可能会在1 s///更unreadeable位(已经非常有吸引力的正则表达式是这样)合并
  • 可以很容易地添加一些关于源日期的安全功能,如错误的日期格式
+0

这已经真的对我有用,我学到了很多东西,谢谢 – tozjerimiah

2

这应该让你开始:

awk -F"[<>]" 'BEGIN {split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",month," ");for (i=1;i<=12;i++) mdigit[month[i]]=i} /<VAL>/ {gsub(/\,/,"")} /<DATE>/ {split($3,a," ");$0=sprintf("<DATE>%s-%02d-%02d</DATE>",a[3],mdigit[a[2]],a[1])}1' file 
<VAL>17451.26</VAL> 
<VAL>353.93</VAL> 
<VAL>395.00</VAL> 
<VAL>2405.00</VAL> 
<DATE>2013-07-31</DATE> 
<DATE>2013-07-31</DATE> 
<DATE>2014-12-31</DATE> 
<DATE>2002-06-21</DATE> 
<DATE>2002-07-10</DATE> 
<MOD>PL</MOD> 
<BATCH>13382</BATCH> 
<TYPE>Invoice</TYPE> 
<REF1>13541/13382</REF1> 
<REF2>671042638320</REF2> 
<NOTES>a-07 final elec</NOTES> 
<SNAME>EDF ENERGY (Electricity)</SNAME> 
<VAL>55.22</VAL> 
</CLT> 
<CLT> 
<CHD>MAT-01</CHD> 
<OPN>U5U1</OPN> 
<PERIOD>07 2013</PERIOD> 
<DATE>2013-06-13</DATE> 
<DATE>2002-07-10</DATE> 
<DATE>2002-07-10</DATE> 
<DATE>2007-08-21</DATE> 
<DATE>2002-07-10</DATE> 
<VAL>-4122322.03</VAL> 
+0

辉煌 - 我找到了这个:http://stackoverflow.com/questions/14342108/converting-months-between-numeric-and- number-using-awk - 您能否展示如何将解决方案与您的解决方案集成在一起,以便只需要通过一次文件传递? – tozjerimiah

+0

感谢您的编辑 - 我得到了'awk:fatal:不匹配(或\(:/ {split($ 3,a,“”); $ 0 = sprintf(“%s-%02d-%s tozjerimiah

+0

@tozjerimiah复制过去的错误,并且在月和日中添加了'%0d'来获取正确的数字 – Jotne

1

你输入好像XML。我会使用适当的XML处理工具,例如XML::XSH2,Perl的XML::LibXML周围的包装:

open file.xml ; 
for //VAL set . xsh:subst(., ',', '','g') ; 
perl { use Time::Piece } ; 
for my $d in //DATE { 
    $t = $d/text() ; 
    set $d/text() { Time::Piece->strptime($t, '%d %b %Y')->ymd } ; 
} 
save :b ; 
+0

寻找速度,因为它是一个很长的文件 - 谢谢你 – tozjerimiah

1

这可能会为你工作(GNU sed的&的bash):

sed -r '/^<VAL>/s/,//g;/^(<DATE>)(.*)(<\/DATE>)$/s//echo "\1"$(date -d "\2" +%F)"\3"/e' file 

这消除了对开始<VAL>线,并为那些包含日期行所有的逗号标记,使用date实用程序和替换命令中的评估标志将日期重新排列为YYYY-MM-DD

的备选解决方案,仅使用SEDS命令:

sed -r '/^<VAL>/s/,//g;/^<DATE>/!b;s/$/\nJan01Feb02Mar03Apr04May05Jun06Jul07Aug08Sep09Oct10Nov11Dec12/;s/^(<DATE>)(..) (...) (....)(<\/DATE>\n).*\3(..)/\1\4-\6-\2\5/;P;d' file 

追加的查找到date线的末端,并使用正则表达式来重新排列输出。

+0

感谢你的帮助 – tozjerimiah