CSV Split field to check multiple codes

Hello,

For work i am trying to generate a combined csv file excisting out of 2 other csv files.

The problem i am facing is that the first field on both files have multiple values in there which arent always the same. This first field is also the joining part.

The layout of the files is as follows:
File1: EAN, Articlenr(our own)
File2: EAN, Articlenr(Supplier), SKU, Stock, Price

The first field can contain more then 1 EAN code in the following format:

Barcode;Sku
4960999865300;testnderp
1230000000009, 1240000000009;ND009
1230000000010, 1240000000010;ND010

Same goes for file 2.

Does anyone know a way how i can split the EAN codes so i can search them in the other file to combine both lines into 1 in another csv file?

HUGE ASSUMPTION WARNING
I am assuming that the EAN code is unique across both files for any one product...

ALSO UNTESTED CODE WARNING, but the germ of an idea

perl -ne '
BEGIN{
  open (my $our_file,"<","/path/to/file1/with/just/ean/and/sku");
  while (<$our_file>){
    my@r=split/;/,$_;
    for my $ean (split/,/,$r[0]){
      $rec1{$ean}=$_;
    }
  }
}
@r=split/;/,$_;
@ean=split/,/,$r[0];
for $ean (@ean){
  if ($rec1{$ean}){
    @p=split/;/,$rec1{$ean};
    @our_eans=split/,/,$p[0];
    my %eans;
    for (@ean,@our_ean){
      $eans{$_}++;
    }
    print join(";",join(",",keys %eans),$p[1],@r[1,2,3]),"\n";
  }
}' path/to/file2 >merged_file.csv

You are correct to assume that the 1 of the EAN codes in both files are the same in which case the 2 lines need to be joined together.

I will test your code asap and let you know if it works. Thank for for helping in advance.

How about supplying samples of all input files and the desired output?

Sorry i totally forgot to add those.

Here are the examples and the output like i would want it.

File 1

Barcode;Sku
4960999865300;testnderp
1230000000001;ND001
1230000000002;ND002
1230000000003;ND003
1230000000008;ND008
1230000000009, 1240000000012;ND009
1230000000010, 1240000000011;ND010

File2

4260236270233,4260236270677,4260236271766;8654951;;10;555.28;Pyr
4960999865300;8935214;0023030102;555;342.70;REV
4006341672544;7345028;0023490;2;555.98;REV
0688334022518;11123553;99263999;555;.01;Pac
0688334022457;123502;;555;.01;Pac
1230000555010, 1240000000010;12345;99263999;555;33.01;Pac

Output file 3:

Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer
4960999865300;testnderp;8935214;0023030102;555;342.70;REV
1230000000010, 1240000000010;ND010;12345;99263999;555;33.01;Pac

I hope this clarifies the combining i am trying to achieve.

I just tested this code and below is the output it creates:

4960999865300;testnderp
;YVVSZN23;21355379;10
1230000000009;ND009
;YVVGZNDG;72051;2
1230000000010;ND010
;YVUVZN01;IOLO-SR-BOX;1

The following was in file 1 and file 2

Barcode;Sku
4960999865300;testnderp
1230000000001;ND001
1230000000009, 1240000000012;ND009
1230000000010, 1240000000011;ND010




4960999865300;YVVSZN23;21355379;10;41,31;Symantec
1230000000009;YVVGZNDG;72051;2;43,10;TEST
1230000000010;YVUVZN01;IOLO-SR-BOX;1;24,79;Diverse

It seems to add the lines from file 2 on a new line instead of behind the original lines but i am not sure how to fix that. Could you check that out?

Why does the second data line appear in the output? There's no match between the files.

---------- Post updated at 11:01 ---------- Previous update was at 10:57 ----------

Try

awk -F";" '
BEGIN           {print "Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer"
                }
NR == FNR       {T[$1] = $2
                 next
                }
$1 in T         {$2 = T[$1] OFS $2
                 print
                }
' OFS=";" file[12]

Hello SDohmen,

I am confuse here by seeing your sample output, as follows are the comments on same.

Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer
4960999865300;testnderp;8935214;0023030102;555;342.70;REV
### Above line you are comparing the first columns of File1 and File2.
1230000000010, 1240000000010;ND010;12345;99263999;555;33.01;Pac
### Above line you are NOT comparing the first column of File1 and File2?

If you want to compare always the first columns of both the Input_files then following may help you.

awk -F"[,|;]" 'FNR==NR{A[$1]=$0;next} ($1 in A){q=$1;sub($1,X);print A[q] $0}' Input_file1 Input_file2

Output will be as follows for above command.

 4960999865300;testnderp;8935214;0023030102;555;11.70;REV
 

If you have some other conditions with your query, I request you to please let us know the complete details on same, it will be helpful for us to help you. Hope this helps.

Thanks,
R. Singh

1 Like
perldoc -f chomp

I did mention it was untested

1 Like

There are 3 lines that contain the same EAN code in both files so those should be able to join together.

---------- Post updated at 11:28 AM ---------- Previous update was at 11:24 AM ----------

Sorry that it looked confusing. I had to manual type them over from the shell. The first column is the one that it should join together as long as 1 of the EAN codes is in both files.

I tested your AWK one-liner and it functions exactly as i needed it. Thank you for that.

I know but i am no perl guru. Sorry :slight_smile:

---------- Post updated at 01:07 PM ---------- Previous update was at 11:28 AM ----------

It seems that the awk line still has a error in there

I just tested it with real data of which there where supposed to be 3 results in the merged file.

Barcode;Sku;Fabrikant
123, 456, 567;microsoftnatural;Microsoft
123456789;testnderp;Acer
1230000000001;ND001;TestMerk
1230000000002;ND002;TestMerk
1230000000003;ND003;TestMerk
1230000000004;ND004;TestMerk
1230000000005;ND005;TestMerk
1230000000006, 9789062387410;ND006;TestMerk
1230000000007;ND007;TestMerk
1230000000008;ND008;TestMerk
0071020493219, 0112040014968, 3609740140679, 4716659214199, 4716659214359, 4716659214373, 8862272143272, 9865745929723;90-IGY7002M00-3PA0;Asus
0886227648320, 0886227648351, 0886227648412, 4053162744332, 4716659648352, 4716659648406, 4716659648413, 8862276483206;90IG00W0-BM3G20;Asus
0681495007080;glohdtest;Kobo
5703887123507;nd1235458;Nilfisk
0889894100573;TST1234;Lenovo
0889233045763;tst1111;Lenovo
PARTNERREF001;PARTNERREF001;Acer
32115464163654;9789062387410;AMD

File2

4716659648413;49200;90IG00W0-BM3G20;8;267,23;ASUS
4716659214199;74277;90-IGY7002M01-3PA0-;7;217,56;ASUS
5703887123507;93631;128470701;5;209,16;Nilfisk

Result

5703887123507;nd1235458;Nilfisk;93631;128470701;5;209,16;Nilfisk

The strange thing is that 1 of the lines works fine but the others dont work. I am guessing that is because of the multiple EAN codes in file 1. When i put the EAN code in the first position it worked fine but on any other position then the first it does not work.

awk  '     
BEGIN           {FS = OFS = ";"
                 print "Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer"
                }
NR == FNR       {gsub (/ /, "", $1)
                 for (n = split($1, T, ","); n > 0; n--) S[T[n]]=$2
                 next
                }
$1 in S         {$2 = S[$1] OFS $2
                 print
                } 
' file[12]
Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer
4716659648413;90IG00W0-BM3G20;49200;90IG00W0-BM3G20;8;267,23;ASUS
4716659214199;90-IGY7002M00-3PA0;74277;90-IGY7002M01-3PA0-;7;217,56;ASUS
5703887123507;nd1235458;93631;128470701;5;209,16;Nilfisk
1 Like

Thank you for the fast reply. I tested it and it seems to work superb of which you have my thanks. 1 question remains though. Could you perhaps explain the code perhaps so i know how it works?

Hello SDohmen,

Following may help you in same.

awk  '                                      
BEGIN           {FS = OFS = ";"                                                   ###### Setting Field seprator and output field seprator as ;
                 print "Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer"    ###### print Barcode;Art_ours;Art_Sup;SKU;stock;price;manufacturer in begining of the code execution.
                }
NR == FNR       {gsub (/ /, "", $1)                                               ###### NR==FNR is a condition which willbe TRUE when first file is being read because FNR is a variable which will have the line number same as NR but FNR's value will be reset each time new file is being read and NR's value will be keep increasing till last file completes.
                 for (n = split($1, T, ","); n > 0; n--) S[T[n]]=$2               ###### starting a for loop here, in which an array named T created whose delimiter is ,(comma) only for $1 because split works on method of split(line/field, array_name, delimiter). Now we are taking the count of array T's element into variable n. and for loop will run till n's value is greater than 0. Then we have created array named S whose index is value of array T's value whose index is variable n and assigning array S's value to $2 of file1.
                 next                                                             ###### Now don't do any further action by next keyword and start from condition NR==FNR.
                }
$1 in S         {$2 = S[$1] OFS $2                                                ###### This will be executed while second file file2 is being read, so $1 in S means, any $1's value which is present in array S, if this is TRUE then perform action where make $2(second field's) value to S[$1] OFS $2's value and assign again it to $2 itself.
                 print                                                            ###### Now print the complete line(with new value of $2, which we had formed in previous step.)
                } 
' file[12]                                                                        ###### mentioning Input_files file1 and file2 here.
 

Thanks,
R. Singh

2 Likes
awk  '
BEGIN           {FS = OFS = ";"                 # set in- and output separator
                 print "Barcode;..."            # print header                
                }
NR == FNR       {gsub (/ /, "", $1)             # remove spaces from first field
                 for (n = split($1, T, ","); n > 0; n--) S[T[n]]=$2
                                                # split SKUs into S array indexed by EANs
                 next                           # skip processing; goto next line
                }
$1 in S         {$2 = S[$1] OFS $2              # if EAN found in S arr: insert SKU into field 2
                 print                          # print modified line
                }
' file[12]
1 Like

thank you both for the excellent information. Even though the code is still a bit garbled for me i am beginning to understand what the code does.

Even though it has been a while before we finally started to use this code below, i am running against a (minor) problem.

#!/bin/sh

awk  '
BEGIN           {FS = OFS = ";"
                 print "ean;sku;pps_reference;mpn;stock;price;manufacturer"
                }
NR == FNR       {gsub (/ /, "", $1)
                 for (n = split($1, T, ","); n > 0; n--) S[T[n]]=$2
                 next
                }
$1 in S         {$2 = S[$1] OFS $2
                 print
                }
' $1 $2 > $3

In file 1 i have the line:
0024066040145,0240660401452,4054318561209,5712505072332;P00000052;Hoya

and in file 2 i have the line:
0024066040145,0240660401452;887024;YDUVP052;50;15.86;Hoya

The strange thing that happens is that it wont join both lines in file 3 even though there are 2 different EAN codes which it can use to join them. Can someone explain how this code needs to be changed so this wont cause an issue?

Try

awk  ' 
BEGIN           {FS = OFS = ";"
                 print "ean;sku;pps_reference;mpn;stock;price;manufacturer"
                }
                {gsub (/ /, "", $1)
                }
NR == FNR       {for (n = split($1, T, ","); n > 0; n--) S[T[n]]=$2
                 next
                }
                {for (n = split($1, T, ","); n > 0; n--) if (T[n] in S) {$2 = S[T[n]] OFS $2
                                                                         print
                                                                         next
                                                                        }
                }
' file[12]
ean;sku;pps_reference;mpn;stock;price;manufacturer
4716659648413;90IG00W0-BM3G20;49200;90IG00W0-BM3G20;8;267,23;ASUS
4716659214199;90-IGY7002M00-3PA0;74277;90-IGY7002M01-3PA0-;7;217,56;ASUS
5703887123507;nd1235458;93631;128470701;5;209,16;Nilfisk
0024066040145,0240660401452;P00000052;887024;YDUVP052;50;15.86;Hoya
1 Like

Sorry for the late reply but i had no chance to test it earlier.

I just changed the code to the one above and it works flawlesly. I am very grateful for the help.