Удалить запятые и отформатировать даты

У меня есть большой файл с такими записями, как:

<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 и изменить даты на ГГГГ-ММ-ДД (например, 2013-07-31) в полях ДАТА.

Ищете быстрый (эффективный) способ сделать это.

Спасибо


person rightwayround    schedule 06.05.2015    source источник
comment
Replace the commas in the VAL fields чем?   -  person Jotne    schedule 06.05.2015
comment
Извините, удалить, а не заменить   -  person rightwayround    schedule 06.05.2015
comment
Взгляните на strtotime() и replace()   -  person Matheno    schedule 06.05.2015


Ответы (4)


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 sed без дополнительной оболочки для преобразования dae
  • дата переформатирования возьмет 2 s///здесь, но может быть объединена в 1 s/// немного более нечитаемым (уже очень привлекательное регулярное выражение, подобное этому)
  • можно легко добавить некоторую функцию безопасности для исходной даты, например неверный формат даты
person NeronLeVelu    schedule 06.05.2015
comment
Это было очень полезно для меня, я многому научился. Спасибо - person rightwayround; 07.05.2015

Это должно помочь вам начать:

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>
person Jotne    schedule 06.05.2015
comment
Великолепно - я нашел это: stackoverflow.com/questions/14342108/ - можете ли вы показать, как решение может быть интегрировано с вашим, чтобы для файла требовался только один проход? - person rightwayround; 06.05.2015
comment
Спасибо за ваше редактирование - я получаю awk: fatal: Unmatched ( or \(: / {split($3,a," ");$0=sprintf("<DATE>%s-%02d-%s</ с этим, однако @Jotne - person rightwayround; 06.05.2015
comment
@tozjerimiah Скопируйте прошлую ошибку. Также добавлено %0d, чтобы получить правильную цифру в месяце и дне. - person Jotne; 06.05.2015

Ваш ввод похож на 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 ;
person choroba    schedule 06.05.2015

Это может сработать для вас (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 и использует регулярное выражение для переупорядочения вывода.

person potong    schedule 06.05.2015