简体   繁体   中英

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? :)

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.

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.

ie: cat input.txt | awk 'BEGIN { OFS=";"; print "ID","Item","Status","Stock" }; /yes/ { print $1,$2,$3,$4 }' 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM