Данные XML в CSV

Awkрешение:

awk 'BEGIN{ FS = OFS = "," }
     NR == 1{ $1 = "LB,-PROJ---,FILENAME----" }
     NR > 1{
         gsub("/(Proj/abc/|conf)", "", $1);
         gsub("/", ",", $1)
    }1' file

Выход:

   LB,-PROJ---,FILENAME----,USER--,DATE-----,TIME---,STATUS
   app,app_pit,HUB_TEST.apx,uJones,4/24/2018,5:55:58,OK
   app,app_pit,test_acqit1.apx,uSmith,3/8/2018,10:16:41,OK
   app,app_pit,test_bkfs.apx,uHarry,/26/2018,9:47:03,OK
0
21.05.2020, 18:53
4 ответа
$ awk '
    BEGIN { FS=",|</?(DN1|AMOUNT)>"; OFS=","; print "Time", "DN1", "AMOUNT" }
    { print $1, $3, $(NF-1) }
' file
Time,DN1,AMOUNT
2020-05-19 19:03:07,99847,49
2020-05-19 19:05:07,92847,19
2020-05-19 19:05:07,947,29

Приведенное выше указывает awk разделить ввод на поля, разделенные строками, которые соответствуют регулярному выражению, хранящемуся в FS(, т.е. ,, <DN1>, </DN1>, <AMOUNT>и </AMOUNT>), а затем выведите 1-е, 3-е и 2-е -последние такие поля.

Вот как в приведенном выше примере каждая запись разбивается на поля:

$ awk -F',|</?(DN1|AMOUNT)>' '{print "----" ORS $0; for (i=1;i<=NF;i++) print NR, i "/" NF, $i}' file
----
2020-05-19 19:03:07,135 INFO [Container : 8504] [HttpUtil.java]requestXML: <?xml version="1.0"? ><COMMAND><TYPE>RCTRFREQ</TYPE><DN1>99847</DN1><AMOUNT>49</AMOUNT></COMMAND> -
1 1/6 2020-05-19 19:03:07
1 2/6 135 INFO [Container : 8504] [HttpUtil.java]requestXML: <?xml version="1.0"? ><COMMAND><TYPE>RCTRFREQ</TYPE>
1 3/6 99847
1 4/6
1 5/6 49
1 6/6 </COMMAND> -
----
2020-05-19 19:05:07,135 INFO [Container : 8504] [HttpUtil.java]requestXML: <?xml version="1.0"? ><COMMAND><PE>RC</PE><DN1>92847</DN1><AMOUNT>19</AMOUNT></COMMAND> -
2 1/6 2020-05-19 19:05:07
2 2/6 135 INFO [Container : 8504] [HttpUtil.java]requestXML: <?xml version="1.0"? ><COMMAND><PE>RC</PE>
2 3/6 92847
2 4/6
2 5/6 19
2 6/6 </COMMAND> -
----
2020-05-19 19:05:07,135 INFO [Container : 8504] [HttpUtil.java]requestXML: <?xml version="1.0"? ><COMMAND><DN1>947</DN1><TYPE>RC</TYPE><AMOUNT>29</AMOUNT></COMMAND> -
3 1/6 2020-05-19 19:05:07
3 2/6 135 INFO [Container : 8504] [HttpUtil.java]requestXML: <?xml version="1.0"? ><COMMAND>
3 3/6 947
3 4/6 <TYPE>RC</TYPE>
3 5/6 29
3 6/6 </COMMAND> -
1
18.03.2021, 23:34

можно выполнить с помощью следующих команд awkи sed:

awk 'BEGIN { FS="AMOUNT|,|DN1" ;OFS=","}; {print $1,$3,$5}' xmlfile | sed 's/<\|>\|\///g' > output.csv
0
18.03.2021, 23:34

Этот случай немного странен для обработки с помощью oneliner, и я бы придерживался обработки XML как объекта XML, а не как строки, поэтому я выбрал Python. Он анализирует дату как строку и находит строку XML, которая будет использоваться для загрузки. Этот подход дает вам больше гибкости, если вы захотите в будущем добавить скрипт для большего количества узлов из XML или других полей в строке ввода.

Первый аргумент, передаваемый сценарию, — ваш входной файл.

#!/usr/bin/python

import sys
import xml.etree.ElementTree as ET


def get_lines():

    file_name = str(sys.argv[1])
    f = open(file_name, 'r')

    return f.readlines()


def print_header():

    print("Time,DN1,AMOUNT")


def process_xml(xml):

    doc = ET.ElementTree(ET.fromstring(xml))
    elements = [
            doc.find("DN1").text,
            doc.find("AMOUNT").text
            ]

    return (",").join(elements)


def process_date(line):

    date = line.split()[:2]
    date = " ".join(date).split(",")[0]

    return date


def process_line(line):

    fields = []
    date = process_date(line)
    xml = process_xml(line.split("<?xml version=\"1.0\"? >")[1][:-3])

    fields.append(date)
    fields.append(xml)

    return (",").join(fields)


def process_all(lines):

    print_header()
    for line in lines:
        print(process_line(line))


if __name__ == "__main__":

    lines = get_lines()
    process_all(lines)

0
18.03.2021, 23:34

Хорошо -структурированные строки можно анализировать с помощьюsed:

sed -En 's|^([^,]+),.*<DN1>(.+)</DN1>.*<AMOUNT>(.+)</AMOUNT>.*|\1,\2,\3|p' file
  • -Eвключает расширенные регулярные выражения
  • -nподавляет автоматическую печать прочитанных строк
  • s|...|___|ищет строку, соответствующую части ..., и заменяет их на___
  • ^([^,]+),соответствует началу до первого ,и помещает его в\1
  • <DN1>(.+)</DN1> matches theДу1 element and puts its content into\2`
  • <AMOUNT>(.+)</AMOUNT>делает то же самое дляAMOUNT
  • \1,\2,\3заменяет результат
  • pгарантирует, что любая совпадающая строка будет напечатана на стандартном выходе
0
18.03.2021, 23:34

Теги

Похожие вопросы