TXR collecting data from a table with ill-defined separator

51 views Asked by At

I have data output that looks like the following:

Item Time    Type   Width     Area      Area    Name
   #   [min]            [m]      [m^2]        %
----|-------|------|-------|----------|--------|---------------------
   1   0.323  A B    0.0000    0.00000  0.00000 ABC                                              
   2   1.581  C      0.0000    0.00000  0.00000 DEF                                              
   3   2.898  D2     0.0000    0.00000  0.00000 GHI                                              
Totals :                       0.00000

The challenge with this data is that there is no obvious column separator other than the position of the | from the line before the data. So, I'm trying to figure out how I can use those character positions to correctly capture the column variables.

It seems to me like the following should work:

@(define os)@/[ ]*/@(end)
Item Time    Type   Width     Area      Area    Name
@(skip 1 1)
@(coll)@{field /(-)+/}@(chr sep)@(until)@(eol)@(end)
@(collect :gap 0 :vars (item time type width area area_pct name))
   @item@(os    )@(chr (toint [sep 0]))@(os)@\
   @time@(os    )@(chr (toint [sep 1]))@(os)@\
   @type@(os    )@(chr (toint [sep 2]))@(os)@\
   @width@(os   )@(chr (toint [sep 3]))@(os)@\
   @area@(os    )@(chr (toint [sep 4]))@(os)@\
   @area_pct@(os)@(chr (toint [sep 5]))@(os)@\
   @name@(os    )@(chr (toint [sep 6]))@(os)@(eol)
@(end)
Totals : @total
@(skip)
@(output)
Item,Time,Type,Width,Area,Area(%),Name
@  (repeat)
@item,@time,@type,@width,@area,@area_pct,@name
@  (end)
@(end)

But none of the rows of data are matching. What am I missing?

The desired output (as a CSV table) is:

Item,Time,Type,Width,Area,Area(%),Name
1,0.323,A B,0.0000,0.00000,0.00000,ABC
2,1.581,C,0.0000,0.00000,0.00000,DEF
3,2.898,D2,0.0000,0.0000,0.00000,GHI

The following code is a "hack" which produces the desired output, but does so leveraging mostly TXR Lisp instead of TXR. The closer I can make the code reflect the data file, the happier my future self will be.

@(define os)@/[ ]*/@(end)
Item Time    Type   Width     Area      Area    Name
@(skip 1 1)
@(coll)@{field /(-)+/}@(chr sep)@(until)@(eol)@(end)
@(collect :gap 0 :vars (item time type width area area_pct name))
@  (cases)
Totals : @(skip)
@    (accept)
@  (or)
@line
@  (set line @(progn (mapdo (lambda (s) (chr-str-set line s #\|)) (rest (reverse sep))) line))
@  (set line @(mapcar 'trim-str (split-str line "|")))
@  (bind item     @[line 0])
@  (bind time     @[line 1])
@  (bind type     @[line 2])
@  (bind width    @[line 3])
@  (bind area     @[line 4])
@  (bind area_pct @[line 5])
@  (bind name     @[line 6])
@  (end)
@(end)
@(skip)
@(output)
Item,Time,Type,Width,Area,Area(%),Name
@  (repeat)
@item,@time,@type,@width,@area,@area_pct,@name
@  (end)
@(end)
0

There are 0 answers