Help needed with multi line text file to CSV

As new starter some hel needed on how to:
I have a multi line text file that needs to be converted to csv.
What node would be the best to start and how to add script to the node, been reading for hours now.
example input
CAR REPORT: STATUS DATA
FILENAME: CARDATA.TXT
TIME: 13:01
DATE: 08MAR2021
CAR TYPE SN: 123-456-4

ROUTE:000001 DATE:08MAR21 TIME:12:01


L WS1 85.3 %
R WS1 85.3 %
L WS2 84.8 %
R WS2 84.8 %
L OAT 749 K
R OAT 771 K
L AB6 106 BAR
R AB6 105 BAR
L WS1 NOISE 0.2 DB
R WS1 NOISE 0.2 DB
L WS2 NOISE 0.2 DB
R WS2 NOISE 0.1 DB
L WATER TEMP 106 K
R WATER TEMP 104 K
L WATER PRESSURE 70 BAR
R WATER PRESSURE 73 BAR

ROUTE:00002 DATE:08MAR20 TIME:11:31


L WS1 89.3 %
R WS1 89.4 %
L WS2 89.8 %
R WS2 89.8 %
L OAT 840 K
R OAT 858 K
L AB6 209 BAR
R AB6 210 BAR
L WS1 NOISE 0.2 DB
R WS1 NOISE 0.2 DB
L WS2 NOISE 0.2 DB
R WS2 NOISE 0.1 DB
L WATER TEMP 106 K
R WATER TEMP 103 K
L WATER PRESSURE 72 BAR
R WATER PRESSURE 74 BAR

then convert this to CSV like with one header line
Date,Time,Route, L WS1, R WS2,L WS2........,R WATER PRESSURE
then the values , separated for each block off data.

Your help where to start is very appreciated.

2 questions...

  1. Is this 1 single file?
  2. do you REALLY need CSV? - what is your end goal?

Also, since posting a copy probably removes hidden characters / changes the newline type, can you attach an actual file (instead of posting text)?

Yes, but the original file is normally longer, just added the first 2 datablocks.
end goal is to store in influxdb and visualize.
For visualization not sure Grafana or Node red.
Now got the message new users cannot upload files.
Data is normal ASCII (windows /r/n)

Then you dont want CSV. You want an object with properties.

Without a test file I am not going to attempt to offer a solution as it will likely be subtly different to the HTML encased forum copy/paste post. You dont need to post a full file, trim it to 2 or 3 entries.

CAR01.txt (1.5 KB)

Here you go...

Its not pretty and there is minimal error checking but it should get you moving.

[{"id":"6393d8f.bc37b28","type":"inject","z":"c559743c.82b088","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":1620,"y":1340,"wires":[["2f5d65cf.529caa"]]},{"id":"2f5d65cf.529caa","type":"file in","z":"c559743c.82b088","name":"","filename":"CAR01.txt","format":"utf8","chunk":false,"sendError":false,"encoding":"none","x":1780,"y":1340,"wires":[["15f8df5b.b049b1"]]},{"id":"15f8df5b.b049b1","type":"function","z":"c559743c.82b088","name":"","func":"const ROUTEHEADER = /ROUTE:(\\d+)\\s+DATE:(.*)$/\nconst ROUTESEP = \"------------------------------------\";\nconst ROUTEENTRY = /(.+)\\s\\s+(\\d+\\.*\\d*)/\n\nconst data = msg.payload.split(\"\\n\")\nconst result = {\n    routes: []\n};\n\nSkipBlankLines(data);\nReadFileHeader(data);\n\nwhile(data.length) {\n    SkipBlankLines(data);\n    var route = ReadRoute(data);\n    if(route) result.routes.push(route);\n}\n\nmsg.payload = result;\nreturn msg;\n\n\nfunction ReadFileHeader(lines) {\n    //while((lines.shift() + \"\").trim())\n    while(lines.length && (lines[0] + \"\").trim() ) {\n        let line = (lines.shift() + \"\").trim(); \n        let parts = line.split(\":\");\n        if(parts.length != 2) continue;\n        let key = parts[0].trim();\n        let val = parts[1].trim();\n        result[key] = val;\n    }\n    return lines.length > 0;\n}\n\nfunction SkipBlankLines(lines) {\n    while( (lines[0] + \"\").trim() == \"\" ) {\n        lines.shift(); \n    } \n    return lines.length > 0;\n}\n\nfunction GetNextRouteHeader(lines) {\n    //while((lines.shift() + \"\").trim())\n    while(lines.length && !ROUTEHEADER.test(lines[0]) ) {\n        lines.shift()\n    }\n    if(!lines.length) return null;\n    var h = (lines.shift() + \"\").trim();\n    var routeHeader = h.match(ROUTEHEADER);\n    return {\n        ROUTE: routeHeader[1],\n        DATE : routeHeader[2]\n    }\n}\n\n\nfunction FindRouteSep(lines) {\n    //while((lines.shift() + \"\").trim())\n    while(lines.length && lines[0] != ROUTESEP ) {\n        lines.shift()\n    } \n    return lines.length > 0;\n}\n\nfunction ReadRoute(lines) {\n    var route = GetNextRouteHeader(lines);\n    if(!route) return null;\n    if(!FindRouteSep(lines)) {\n        return null;\n    }\n    lines.shift()//remove separator------\n    SkipBlankLines(lines);\n    \n    //read entries\n    while( lines.length && ROUTEENTRY.test((lines[0] + \"\").trim())  ) {\n        const l = (lines.shift() + \"\").trim();\n        const match = l.match(ROUTEENTRY);\n        let name = (match[1]+\"\").trim();\n        let value = (match[2]+\"\").trim();\n        route[name] = Number(value);\n    }\n    return route;\n}\n\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":1630,"y":1400,"wires":[["ed22be37.36a5c"]]},{"id":"ed22be37.36a5c","type":"debug","z":"c559743c.82b088","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":1800,"y":1400,"wires":[]}]
1 Like

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.