Reputation: 47
I have a Pipe-delimited CSV from a company report production. But there is a 'comment' field that the data inputted randomly by the employee and causes failed to load the data into database. How do i solve it using UNIX command or shell script?
The data sample is look like this :
Employee ID|Time Type|Start Date|End Date|Number Of Days|Comment|Approved
90006731|Leave|04/02/2019|04/02/2019|1|annual leaves|Y
90005267|Leave|04/02/2019|04/02/2019|1||Y
90007366|Leave|04/02/2019|04/02/2019|1|* Take care of vehicle taxes
* Vehicle Repair
* Community service
* Swimming|Y
90005052|Leave|04/02/2019|04/02/2019|1|Son's field trip|Y
90006253|Death of Wife/Husband/Child/Parent|04/01/2019|04/02/2019|2||Y
90007595|Leave|04/01/2019|04/01/2019|1|family plan|Y
90004064|Leave|08/18/2020|08/21/2020|3|Dear Mas Rama,
Please kindly approve, Mas Okto was oke.
Thanks.|Y
90007072|Sick Leave Without Certificate|04/01/2019|04/01/2019|1|Sick leave due to eye swelling|Y
90004371|Sick Leave|04/01/2019|04/05/2019|4||Y
90007431|Sick Leave|04/01/2019|04/01/2019|1||Y
Required Output :
Employee ID|Time Type|Start Date|End Date|Number Of Days|Comment|Approved
90006731|Leave|04/02/2019|04/02/2019|1|annual leaves|Y
90005267|Leave|04/02/2019|04/02/2019|1||Y
90007366|Leave|04/02/2019|04/02/2019|1|* Take care of vehicle taxes * Vehicle Repair * Community service * Swimming|Y
90005052|Leave|04/02/2019|04/02/2019|1|Son's field trip|Y
90006253|Death of Wife/Husband/Child/Parent|04/01/2019|04/02/2019|2||Y
90007595|Leave|04/01/2019|04/01/2019|1|family plan|Y
90004064|Leave|08/18/2020|08/21/2020|3|Dear Mas Rama, Please kindly approve, Mas Okto was oke. Thanks.|Y
90007072|Sick Leave Without Certificate|04/01/2019|04/01/2019|1|Sick leave due to eye swelling|Y
90004371|Sick Leave|04/01/2019|04/05/2019|4||Y
90007431|Sick Leave|04/01/2019|04/01/2019|1||Y
I have tried [this][1],
awk -F\| '{ while (NF < 7 || $NF == "") { brokenline=$0; getline; $0 = brokenline $0}; print }' cu_inf_20200902tst.csv > cu_inf_20200902tst1.csv
but i found the error warning :
awk: cmd. line:1: (FILENAME=cu_inf_20200902tst.csv FNR=19) fatal: grow_fields_arr: fields_arr: can't allocate 321069040 bytes of memory (Cannot allocate memory)
Any suggest to fix my problem? [1]: https://unix.stackexchange.com/questions/434979/fixing-malformed-csv-with-incorrect-new-line-chars-using-sed-or-perl-only
Upvotes: 4
Views: 276
Reputation: 58430
This might work for you (GNU sed):
sed ':a;s/[^|]*/&/7;t;N;s/\n//;ta' file
Check to see if the current line contains 7 fields, if not, append the next line, remove the newline and repeat.
Upvotes: 1
Reputation: 133528
Considering that your first field id will be always 8 digits and no other field will be of 8 digits like it, if this is the case then you could try following.
awk '
{
printf("%s%s", (FNR>1 ? (/^[0-9]{8}/?ORS:OFS) : ""), $0)
}
END{
print ""
}' Input_file
Explanation: Adding detailed explanation for above.
awk ' ##Starting awk program from here.
{
printf("%s%s",(FNR>1?(/^[0-9]{8}/?ORS:OFS) ""), $0) ##Using printf statement from here where checking condition if line is first line then check if line starts from 8 digits then print new line else print space.
}
END{ ##Starting END block of this program from here.
print "" ##Printing a new line in here.
}' Input_file ##Mentioning Input_file name here.
OR(in case you want to keep header separate itself then keep its condition separate itself)
awk '
FNR==1{
print
next
}
{
printf("%s%s",$0!~/^[0-9]{8}/?OFS:(FNR>2?ORS:""),$0)
}
END{
print ""
}' Input_file
Explanation: Adding detailed explanation for above.
awk ' ##Starting awk program from here.
FNR==1{ ##Checking condition if this is first line then do following.
print ##Printing current line here.
next ##next will skip all further statements from here.
}
{
printf("%s%s",$0!~/^[0-9]{8}/?OFS:(FNR>2?ORS:""),$0) ##Using printf for printing where checking condition if line starts from 8 digits then print space else check if line number is more than 2 then print new line or nothing with current line.
}
END{ ##Starting END block of this program from here.
print "" ##Printing a new line in here.
}' Input_file ##Mentioning Input_file name here.
Upvotes: 2
Reputation: 960
Please try the following.
Sed Solution
sed ':a;N;/\n[0-9]/!s/\n/ /;ta;P;D' input_file
awk Solution
awk '{printf "%s%s", (NR>1 ? (/^[0-9]/?ORS:OFS) : ""), $0} END{print ""}' input_file
Output of the following command
Employee ID|Time Type|Start Date|End Date|Number Of Days|Comment|Approved
90006731|Leave|04/02/2019|04/02/2019|1|annual leaves|Y
90005267|Leave|04/02/2019|04/02/2019|1||Y
90007366|Leave|04/02/2019|04/02/2019|1|* Take care of vehicle taxes *Vehicle Repair * Community service * Swimming|Y
90005052|Leave|04/02/2019|04/02/2019|1|Son's field trip|Y
90006253|Death of Wife/Husband/Child/Parent|04/01/2019|04/02/2019|2||Y
90007595|Leave|04/01/2019|04/01/2019|1|family plan|Y
90004064|Leave|08/18/2020|08/21/2020|3|Dear Mas Rama, Please kindly approve, Mas Okto was oke. Thanks.|Y
90007072|Sick Leave Without Certificate|04/01/2019|04/01/2019|1|Sick leave due to eye swelling|Y
90004371|Sick Leave|04/01/2019|04/05/2019|4||Y
90007431|Sick Leave|04/01/2019|04/01/2019|1||Y
for detail explanatiion: How to join lines not starting with specific pattern to the previous line in UNIX?
Upvotes: 1