jayFour
jayFour

Reputation: 25

parsing a list file (awk/bash)

What i'm going to do is creating a csv file out of a parsed list.

[input.txt]

This is a list of all gadgets.
Version: 11
Created by: jayFour

1  Toy    no    ordered  
2  Box    no    ordered  
3  Spade  yes   in_stock  
4  Nail   yes   in_stock  
5  Chair  no    ordered
6  Table  yes   in_stock
7  Apple  no    ordered
9  Phone  yes   in_stock

# generated 2014

Now i created a script, which should do an 'awk' and create me a csv file like this:

[output.csv]

| ID  |  Item  |  Status  |  Stock     |  
|  3  |  Spade |  yes     |  in_stock  |  
|  4  |  Nail  |  yes     |  in_stock  |
|  6  |  Table |  yes     |  in_stock  |
|  9  |  Phone |  yes     |  in_stock  |

"|" represents the table borders.

Script:

#!/bin/bash

ifiles=`ls input.txt`

for ifile in $ifiles
do
  echo "ID;Item;Status;Stock\r" > output.csv
  id=`awk '/yes/' $ifiles | awk {'print $1'}`
  itm=`awk '/yes/' $ifiles | awk {'print $2'}`
  stat=`awk '/yes/' $ifiles | awk {'print $3'}`
  stck=`awk '/yes/' $ifiles | awk {'print $4'}`
  echo "$id;$itm;$stat;$stck\r" >> output.csv
done

As you can imagine, that did not work this way. I got issues with breaks within my csv (maybe caused by faulty read-in/parsing my input-file line by line.

Well - How to fix? :)

Upvotes: 1

Views: 1340

Answers (2)

Ed Morton
Ed Morton

Reputation: 203209

Start with this:

awk -v OFS=';' '
BEGIN { print "ID","Item","Status","Stock" }
$3=="yes" { $1=$1; print }
' $ifiles

Let us know if anything needs to change. Note that I'm leaving $ifiles unquoted as you did under the assumption you need to do that and understand all the associated caveats.

Upvotes: 2

Tensibai
Tensibai

Reputation: 15784

this achieve what you wish:

cat input.txt | awk 'BEGIN { print "ID;Item;Status;Stock" }; /yes/ { printf "%s;%s;%s;%s\n", $1,$2,$3,$4 }'

To be placed inside your loop of course.

Explanation: start by printing the Header (BEGIN block) then for each line whith a yes, print each field separated by a ';'

There's more elegant way for this in awk, but they are less easy to understand at first.

i.e: cat input.txt | awk 'BEGIN { OFS=";"; print "ID","Item","Status","Stock" }; /yes/ { print $1,$2,$3,$4 }'

Here I let awk manage the output by giving him the Output Field Separator (OFS) within the BEGIN block;

Output is:

ID;Item;Status;Stock
3;Spade;yes;in_stock
4;Nail;yes;in_stock
6;Table;yes;in_stock
9;Phone;yes;in_stock

Edit for completeness: you bash would become:

#!/bin/bash

ifiles=`ls input.txt`
echo "ID;Item;Status;Stock\r" > output.csv

for ifile in $ifiles
do      
  cat $ifile | awk 'BEGIN { OFS=";"}; /yes/ { print $1,$2,$3,$4 }' >> output.csv
done

As you may not want to repeat the header, it is done before the loop and not anymore in the awk part.

Upvotes: 1

Related Questions