Commandline 2 csv files vergelijken

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Ik ben op dit moment bezig om diverse files te vergelijken op de commandline in debian.

De files in kwestie zijn csv files met de volgende layout:
File 1: "Barcode","Sku_Eigen"
File 2: "Barcode","Sku_Lev","Sku_Fab","Inkoop","Verkoop"

Wat wij willen is dat aan de hand van de barcode aan elkaar gekoppeld worden zodat onderstaande file ontstaat:

File 3: "Barcode","Sku_Eigen","Sku_Lev","Sku_Fab","Inkoop","Verkoop"

Ik heb zitten te kijken naar het comm commando in linux maar deze spuugt me de volledige lijst uit zonder te vergelijken. Dit zal vermoedelijk komen doordat alles voorzien is van ",". Dit is echter iets wat ik moet aanhouden om weer te kunnen importeren.

Ook met grep -v kom ik er niet helemaal uit. Weet iemand misschien een makkelijke manier om dit bovenstaande te bewerkstelligen?

-Te huur


Acties:
  • 0 Henk 'm!

  • larshack
  • Registratie: Maart 2007
  • Laatst online: 16-07 22:10

larshack

Zonder melk en suiker

met powershell kun je dit prima doen, array inlezen aan de hand ven CSV-Import

Acties:
  • 0 Henk 'm!

  • Fish
  • Registratie: Juli 2002
  • Niet online

Fish

How much is the fish

Als het éénmalig is zou ik het gewoon in excel doen

Iperf


Acties:
  • 0 Henk 'm!

  • begintmeta
  • Registratie: November 2001
  • Niet online

begintmeta

Moderator General Chat
csvtool of csvkit?

Wat googlen levert ook wel wat suggesties over gebruik van awk op als ik het zo even vluchtig goed heb gezien.

[ Voor 126% gewijzigd door begintmeta op 08-12-2015 13:03 ]


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Bedankt voor de suggesties maar allemaal zijn dit Windows apps waar ik niets aan heb.

De reden waarom we dit op de linux shell doen is puur snelheid en wat makkelijker te onderhouden voor ons. Tevens hebben we geen losse licenties liggen waar we nog gebruik van kunnen maken.

Als laatste is natuurlijk ook nog eens van belang dat dit straks in een script verwerkt wordt welke elke paar uur via cron draait.

[Toevoeging]
Ik heb zojuist nog eens wat verder zitten te zoeken en ik zie dat ik 1 ding ben vergeten te melden. Sommige producten hebben meerdere EAN nummers welke in 1 kolom geschreven zijn als volgt: "1230000000009, 1240000000009","SKU009".

Nu heb ik zojuist ook nog onderstaande commando gevonden wat het wel doet samenvoegen echter werkt dit niet met meerdere EAN nummers in 1 kolom. Als iemand daar toevallig een idee voor heeft dan hoor ik het graag.


join -t $',' -1 1 -2 1 -o 1.1 1.2 2.2 2.3 2.4 2.5 <(sort -t $',' -k 3,3 website/raw.csv) <(sort actebis/clean.csv) > test.csv

[ Voor 42% gewijzigd door Yagermeister op 08-12-2015 13:15 ]

-Te huur


Acties:
  • 0 Henk 'm!

  • RaZ
  • Registratie: November 2000
  • Niet online

RaZ

Funky Cold Medina

PowerShell heb je ook voor Linux: http://www.microsoft.com/...oad/details.aspx?id=49150

Maar of dat genoeg is voor wat je wil, ik zou het niet weten. Maar het is zeker niet Windows only.

Ey!! Macarena \o/


Acties:
  • 0 Henk 'm!

  • begintmeta
  • Registratie: November 2001
  • Niet online

begintmeta

Moderator General Chat
Yagermeister schreef op dinsdag 08 december 2015 @ 13:05:
Bedankt voor de suggesties maar allemaal zijn dit Windows apps waar ik niets aan heb.
...
Niets van wat ik heb genoemd draait niet desgewenst onder linux meende ik.
RaZ schreef op dinsdag 08 december 2015 @ 13:09:
PowerShell heb je ook voor Linux: http://www.microsoft.com/...oad/details.aspx?id=49150

Maar of dat genoeg is voor wat je wil, ik zou het niet weten. Maar het is zeker niet Windows only.
Weet je dat zeker? Is "Powershell DSC" hetzelfde als "PowerShell'?

[ Voor 40% gewijzigd door begintmeta op 08-12-2015 13:17 ]


Acties:
  • 0 Henk 'm!

Anoniem: 231944

Als je er niet uitgeraakt met awk/join/cut dan kan je misschien proberen een (tijdelijke) sqlite tabel te maken en daarin je csv's te importeren: https://www.sqlite.org/cvstrac/wiki?p=ImportingFiles

Daarna kan je gewoon SQL queries gebruiken die je ook kan dumpen naar CSV.

Powershell op linux gaan installeren lijkt mij voor niets nodig...

Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
RaZ schreef op dinsdag 08 december 2015 @ 13:09:
PowerShell heb je ook voor Linux: http://www.microsoft.com/...oad/details.aspx?id=49150

Maar of dat genoeg is voor wat je wil, ik zou het niet weten. Maar het is zeker niet Windows only.
Sorry dat wist ik helemaal niet. Ik wil echter liever zo min mogelijk extra installeren indien het met normale tools ook opgelost kan worden.
begintmeta schreef op dinsdag 08 december 2015 @ 13:11:
[...]

Niets van wat ik heb genoemd draait niet desgewenst onder linux meen ik.
Ah Sorry, ook dit had ik niet gezien. Echter ook hier wil ik proberen te vermijden dat ik extra tools nodig heb.
Anoniem: 231944 schreef op dinsdag 08 december 2015 @ 13:16:
Als je er niet uitgeraakt met awk/join/cut dan kan je misschien proberen een (tijdelijke) sqlite tabel te maken en daarin je csv's te importeren: https://www.sqlite.org/cvstrac/wiki?p=ImportingFiles

Daarna kan je gewoon SQL queries gebruiken die je ook kan dumpen naar CSV.

Powershell op linux gaan installeren lijkt mij voor niets nodig...
Hier heb ik helaas nog minder ervaring mee dan awk etc.

[ Voor 25% gewijzigd door Yagermeister op 08-12-2015 13:22 ]

-Te huur


Acties:
  • 0 Henk 'm!

  • begintmeta
  • Registratie: November 2001
  • Niet online

begintmeta

Moderator General Chat
Yagermeister schreef op dinsdag 08 december 2015 @ 13:17:
...
Ah Sorry, ook dit had ik niet gezien. Echter ook hier wil ik proberen te vermijden dat ik extra tools nodig heb.
Wat is een 'extra tool', 'grep' en 'join' zijn bijvoorbeeld in zekere zin ook al 'extra tools', net als 'bash'. diverse distributies hebben awk ook wel standaard erin zitten, of perl, of python.... Dus je kan kijken wat je eventueel al hebt.

cvskit (of cvstool) zijn bijvoorbeeld maar kleine tools /(/toolpackages), vaak ook wel met beschikbare packages in de standaard-repositories.

[ Voor 17% gewijzigd door begintmeta op 08-12-2015 13:23 ]


Acties:
  • 0 Henk 'm!

  • Ultraman
  • Registratie: Februari 2002
  • Laatst online: 18-07 20:49

Ultraman

Moderator Harde Waren

Boefje

Er zijn heel aardige tools om met o.a. CSV tools te werken beschikbaar in volgens mij iets als csvtools uit de Python packages hoek, meestal te installeren met pip. Ik heb in mijn bureau @ work een mooi boek liggen hierover "Data Mining on the Commandline" daar worden veel met dit soort tools gewerkt.
Ik zal die straks even opzoeken zodra ik weer binnen ben.

Verder kun je met standaard Unix tools ook vrijwel alles doen. Denk dan aan awk, sed, cut, tr, cut, wc, en die hele mikmak plus wat reguliere expressies.

[ Voor 23% gewijzigd door Ultraman op 08-12-2015 13:23 ]

Als je stil blijft staan, komt de hoek wel naar jou toe.


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
begintmeta schreef op dinsdag 08 december 2015 @ 13:21:
[...]

Wat is een 'extra tool', 'grep' en 'join' zijn bijvoorbeeld in zekere zin ook al 'extra tools', net als 'bash'. diverse distributies hebben awk ook wel standaard erin zitten, of perl, of python.... Dus je kan kijken wat je eventueel al hebt.

cvskit (of cvstool) zijn bijvoorbeeld maar kleine tools /(/toolpackages), vaak ook wel met beschikbare packages in de standaard-repositories.
Ik zie inderdaad dat csvtool een redelijk klein package is echter zijn de andere al standaard geinstalleerd. Dat is wat ik eigenlijk bedoel met de standaard tools. Ik wil juist proberen zo min mogelijk extra te installeren als dat niet nodig is. Dit is ook juist de reden waarom wij voor linux gekozen hebben omdat veel van dit soort dingen gewoon al kan via de commandline zonder extra software te installeren.
Ultraman schreef op dinsdag 08 december 2015 @ 13:22:
Er zijn heel aardige tools om met o.a. CSV tools te werken beschikbaar in volgens mij iets als csvtools uit de Python packages hoek, meestal te installeren met pip. Ik heb in mijn bureau @ work een mooi boek liggen hierover "Data Mining on the Commandline" daar worden veel met dit soort tools gewerkt.
Ik zal die straks even opzoeken zodra ik weer binnen ben.

Verder kun je met standaard Unix tools ook vrijwel alles doen. Denk dan aan awk, sed, cut, tr, cut, wc, en die hele mikmak plus wat reguliere expressies.
Dat zou super zijn. Let wel, het enigste wat nu overblijft is werken met de meerdere EAN nummers aangezien join dat net niet grappig vindt. Ik gok dat ik daarvoor juist wel met een csvtool ofzo moet werken.

-Te huur


Acties:
  • 0 Henk 'm!

  • daft_dutch
  • Registratie: December 2003
  • Laatst online: 09-07 18:45

daft_dutch

>.< >.< >.< >.<

lolz.. ik val erg in herhaling bij dit soort vragen.
gebruik reguliere expressies samen met een echte script taal. Php Perl Pyton.

[ Voor 23% gewijzigd door daft_dutch op 08-12-2015 14:09 ]

>.< >.< >.< >.<


Acties:
  • 0 Henk 'm!

  • CAPSLOCK2000
  • Registratie: Februari 2003
  • Laatst online: 16-07 10:55

CAPSLOCK2000

zie teletekst pagina 888

Er is geen tool die precies doet wat je wil, dat is zelden zo ;)

De kracht van bash is dat je het gebruikt als lijm om andere tools mee aan elkaar te plakken.
De grote kracht is het gebrek aan datastructuren.


De kunst van werken met bash is alles in kleine stappen opsplitsen zodat het wel kan met de tools die je hebt.
Ik zou dus niet op zoek gaan naar een betere join maar naar een manier om de data zo aan te bieden dat join het wel snapt.

Je zou de data kunnen preprocessen en zorgen dat er geen dubbele regels voorkomen. Dat je kunnen doen door op te splitsen in kleinere files met 1 regel per file. Dan kun je die weer samenvoegen met join.

This post is warranted for the full amount you paid me for it.


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Je kan met awk de eerste kolom uitlezen en die vergelijken tussen de twee bestanden. Dan voeg je het tweede veld van het eerste bestand toe aan de bijbehorende regel van het tweede bestand. Je parset de boel dan regel voor regel, het eerste bestand doorloop je 1x, het tweede bestand doorloop je elke keer dat je een regel verder gaat in bestand 1. De matchende regels spuug je uit naar een apart bestand via append (>>).

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op dinsdag 08 december 2015 @ 15:27:
Je kan met awk de eerste kolom uitlezen en die vergelijken tussen de twee bestanden. Dan voeg je het tweede veld van het eerste bestand toe aan de bijbehorende regel van het tweede bestand. Je parset de boel dan regel voor regel, het eerste bestand doorloop je 1x, het tweede bestand doorloop je elke keer dat je een regel verder gaat in bestand 1. De matchende regels spuug je uit naar een apart bestand via append (>>).
Heb je hier misschien een voorbeeld van? Ik snap wel wat je bedoelt maar ik zou niet weten hoe ik dit moet scripten

-Te huur


Acties:
  • 0 Henk 'm!

  • TweakMDS
  • Registratie: Mei 2002
  • Laatst online: 12:50
Leuke case, de commandline tools binnen linux, zoals sed, awk etc zijn erg krachtig, maar iets zegt me dat je in dit geval niet alleen de headers van je CSV bestanden wil joinen maar ook de regels, en dat die niet 1 op 1 matchen.
Wat ik zou doen is hier een sqlite bij betrekken. Je kan vrij simpel met enkel een commandline een bestand inlezen in een virtual table. Dat doe je dan voor beide regels, en vervolgens kan je deze met elkaar joinen en weer exporteren. Uiteindelijk zal je wel wat aannames moeten doen over de kolom waar je je join op legt (bijvoorbeeld barcode).

Dat lijkt me niet heel complex te scripten.

Alternatief is simpeler maar zou zo maar kunnen werken: join.
Zie hier een bijna identieke vraag http://unix.stackexchange...les-with-matching-columns
Overigens staat in dat laatste ook een prima awk voorbeeld.

Edit: zoiets simpels zou het kunnen zijn:
code:
1
join -t, -1 1 -2 1 file1.csv file2.csv

Edit 2: ik had je edit gemist. Ik zou eigenlijk nog steeds de join optie handhaven maar dan mogelijk het bestand eerst pre-processen waardoor je die gecombineerde regels in twee regels hakt. Dat klinkt echt als een awk dingetje.
Als je overigens vaker van dit soort werk doet is awk leren wel echt een aanrader. De combinatie sed+awk is bijna onmogelijk te verslaan als je ook maar iets met tekstbestanden doet.

[ Voor 42% gewijzigd door TweakMDS op 08-12-2015 15:54 ]


Acties:
  • 0 Henk 'm!

  • downtime
  • Registratie: Januari 2000
  • Niet online

downtime

Everybody lies

RaZ schreef op dinsdag 08 december 2015 @ 13:09:
PowerShell heb je ook voor Linux: http://www.microsoft.com/...oad/details.aspx?id=49150

Maar of dat genoeg is voor wat je wil, ik zou het niet weten. Maar het is zeker niet Windows only.
PowerShell is zeker Windows-only en zal dat ook wel blijven, PowerShell zou op Linux als een vis op het droge zijn. Het product waar je naar linkt is alleen maar een DSC-agent die zo te zien Python scripts gebruikt.

Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Voor mij maakt dit van powershell niet echt uit aangezien ik dat echt niet wil gaan gebruiken met de standaard tools zoals awk en sed die er al zijn.

Om even wat voorbeelden te geven van de scripts die ik op dit moment al gemaakt heb. Let wel deze zijn verre van compleet en zijn op dit moment puur even zodat de omzetting plaatsvindt. Op een later moment moet ik ze opschonen en verbeteren natuurlijk.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#!/bin/sh

cd leverancier

curl -u xxx:xxx -O ftp://ftp/pricelist.csv

mv *.csv prijslijst.csv

cut -d";" -f1,4,7-10 prijslijst.csv > raw.csv

rm prijslijst.csv

sed 's/> //g' raw.csv > raw2.csv

awk -F';' '$4!=""' raw2.csv > raw3.csv

awk 'BEGIN { FS="\;"; OFS="\t"; } {print $4","$5","$6","$7","$8","$9,$2,$3,$11,$10}' raw4.csv > clean.csv

cd ..


In het kort doet deze het volgende. Hij download de prijslijst van de leverancier. Deze doet die renamen zodat het wat makkelijker verwerken is (is eigenlijk niet meer nodig na alle aanpassingen maar sommige leveranciers willen nog wel eens graag de hele ascii tabel gebruiken).

Hierna worden de voor mij belangrijke kolommen eruit gehaald. Daarna met sed wordt de voorraad gestript van >. Als volgende stap wordt gekeken of de eerste kolom met EAN nummers leeg is en zo ja worden die eruit gehaald. Daarna gebeurt als laatste stap nog dat de kolommen op de goede volgorde gezet worden met in kolom 1 een samenvoeging van alle voorgaande kolommen met daarin EAN nummers.

Het enigste wat ik nog moet oplossen is dat op dit moment de output van kolom 1: 426001085234235,,,,, is. Hier moet ik dus nog de comma's weghalen. Ook moet ik natuurlijk dit alleen bij kolom 1 doen en opletten dat sommige regels meer als 1 ean nummer hebben waardoor het aantal comma's ook veranderd.

-Te huur


Acties:
  • 0 Henk 'm!

  • Thc_Nbl
  • Registratie: Juli 2001
  • Laatst online: 21-05 22:24
ik zou daar een "tr" tegenaan gooien.

tr -d","

weg zijn je comma's
kan volgens mij al in deze:

cut -d";" -f1,4,7-10 prijslijst.csv | tr -d"," > raw.csv
of met sed
cut -d";" -f1,4,7-10 prijslijst.csv | sed 's/,//g' > raw.csv

[ Voor 18% gewijzigd door Thc_Nbl op 14-12-2015 13:37 ]

ehhh.. noppes


Acties:
  • 0 Henk 'm!

  • RemcoDelft
  • Registratie: April 2002
  • Laatst online: 03-05 10:30
Yagermeister schreef op dinsdag 08 december 2015 @ 12:39:
De files in kwestie zijn csv files met de volgende layout:
File 1: "Barcode","Sku_Eigen"
File 2: "Barcode","Sku_Lev","Sku_Fab","Inkoop","Verkoop"
Als eenvoudige snelle oplossing zou ik even tempfiles maken genaamd "barcode" en daar de betreffende data instoppen. Vervolgens plak je die aan elkaar tot de gewenste file.
Afhankelijk van het aantal regels kan dit erg snel of erg lang duren.
Ik heb zitten te kijken naar het comm commando in linux maar deze spuugt me de volledige lijst uit zonder te vergelijken. Dit zal vermoedelijk komen doordat alles voorzien is van ",". Dit is echter iets wat ik moet aanhouden om weer te kunnen importeren.
Ik ben niet bekend met comm, maar helpt het als je de komma even vervangt door een spatie (met `sed`)?

Acties:
  • 0 Henk 'm!

  • FRidh
  • Registratie: Januari 2004
  • Laatst online: 08:53
en dan nog een oplossing met Blaze.


Python:
1
2
3
4
5
6
from blaze import Data, join
from odo import odo

file1 = Data('file1.csv')
file2 = Data('file2.csv')
odo(join(file1, file2), 'file3.csv')


Edit:

Ik zag net pas wat je schreef over meerdere EAN nummers. Heeft alleen File 1 mogelijk meerdere entries in EAN, of File 2 ook? Als ze beide dezelfde waarden hebben dan zal bovenstaande scriptje werken.

Wat je anders waarschijnlijk moet doen (afhankelijk van wat je wilt natuurlijk) is de strings splitten, en vervolgens het uitwendig product nemen.

Python:
1
odo(join(file1, file2, how='outer'), 'file3.csv')

[ Voor 44% gewijzigd door FRidh op 14-12-2015 18:16 ]

Research is to see what everybody else has seen, and to think what nobody else has thought - Albert Szent-Györgyi


Acties:
  • 0 Henk 'm!

  • donderdraak
  • Registratie: Juni 2002
  • Laatst online: 09-07-2017
Daar hebben we niks aan.

[ Voor 89% gewijzigd door CAPSLOCK2000 op 14-12-2015 18:22 ]


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
RemcoDelft schreef op maandag 14 december 2015 @ 13:42:
[...]

Als eenvoudige snelle oplossing zou ik even tempfiles maken genaamd "barcode" en daar de betreffende data instoppen. Vervolgens plak je die aan elkaar tot de gewenste file.
Afhankelijk van het aantal regels kan dit erg snel of erg lang duren.


[...]

Ik ben niet bekend met comm, maar helpt het als je de komma even vervangt door een spatie (met `sed`)?
Dit ga ik eens uitproberen maar ik denk dat ik ga kijken of ik gewoon de regel kan overslaan als die leeg is terwijl ik die regels hersorteer op onderstaande regel.

awk 'BEGIN { FS="\;"; OFS="\t"; } {print $4","$5","$6","$7","$8","$9,$2,$3,$11,$10}' raw4.csv > clean.csv

Dat zou als het goed is mogelijk moeten zijn maar ik moet nog uitzoeken hoe.
FRidh schreef op maandag 14 december 2015 @ 17:34:
en dan nog een oplossing met Blaze.


Python:
1
2
3
4
5
6
from blaze import Data, join
from odo import odo

file1 = Data('file1.csv')
file2 = Data('file2.csv')
odo(join(file1, file2), 'file3.csv')


Edit:

Ik zag net pas wat je schreef over meerdere EAN nummers. Heeft alleen File 1 mogelijk meerdere entries in EAN, of File 2 ook? Als ze beide dezelfde waarden hebben dan zal bovenstaande scriptje werken.

Wat je anders waarschijnlijk moet doen (afhankelijk van wat je wilt natuurlijk) is de strings splitten, en vervolgens het uitwendig product nemen.

Python:
1
odo(join(file1, file2, how='outer'), 'file3.csv')
de 2de file heeft maar 1 ean nummer. Alleen de eerste file heeft er meerdere. Het is me inmiddels ook gelukt om deze te joinen middels het join commando. Alleen hapert die op meerdere ean nummers.

-Te huur


Acties:
  • +1 Henk 'm!

  • Donaldinho
  • Registratie: November 2002
  • Laatst online: 18-07 07:46
In bash heb ik hem zo opgelost, kan nog wat optimalisatie in, maar goed

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
#set -x

#File 1: "Barcode","Sku_Eigen"
#File 2: "Barcode","Sku_Lev","Sku_Fab","Inkoop","Verkoop"
#File 3: "Barcode","Sku_Eigen","Sku_Lev","Sku_Fab","Inkoop","Verkoop"

FILE1=file1
FILE2=file2

while read line ;do
        barcode=`echo $line|cut -d, -f1`
        base=`grep $barcode $FILE1`
        full=`grep $barcode $FILE2|awk -F',' '{print $2 "," $3 "," $4 "," $5 "," $6}'`
        echo -ne $base","$full"\n"
done < $FILE1


dus wat ik doe:
- in een loop uit file1 haal ik eerst barcode eruit
- dan sla ik de vollledige regel van die specifieke barcode uit file1 op in een variabele
- grep naar barcode in file2, waarbij omdat file2 altijd zelfde formaat heeft, ik met awk alles behalve veld 1 in tweede variabele zet
- daarna variabele 1 en 2 op een regel displayen

het kan vast eleganter, maar dit werkt ook .

[ Voor 5% gewijzigd door Donaldinho op 14-12-2015 21:22 ]

You almost can’t blame him or the other diet gurus for leaning in on the techno-bullshit market; it’s hard to fill up a 300 page diet book on “eat a bit less and find a type of exercise that doesn’t make you hate life.”


Acties:
  • 0 Henk 'm!

  • Rainmaker
  • Registratie: Augustus 2000
  • Laatst online: 14-07-2024

Rainmaker

RHCDS

Yagermeister schreef op dinsdag 08 december 2015 @ 13:05:
De reden waarom we dit op de linux shell doen is puur snelheid en wat makkelijker te onderhouden voor ons.
Bash is in de regel juist niet "snel".

Snel is C of C++. Misschien compiled perl.
Een (mooie) tussenvorm is Python. Redelijk snel en redelijk makkelijk te onderhouden. En staat redelijk standaard op ieder Linux systeem. Zeker omdat hier gewoon standaard modules voor bestaan (zoals de hierboven aangegeven blaze, ook al kende ik die zelf nog niet. Maar er is ook een "csv" module. Ander voorbeeld is deze module, waar dit mergen gewoon in de voorbeelden staat).
[b][message=45437347,noline]Donaldinho schreef op maandag 14 december 2015 @
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
#set -x

#File 1: "Barcode","Sku_Eigen"
#File 2: "Barcode","Sku_Lev","Sku_Fab","Inkoop","Verkoop"
#File 3: "Barcode","Sku_Eigen","Sku_Lev","Sku_Fab","Inkoop","Verkoop"

FILE1=file1
FILE2=file2

while read line ;do
        barcode=`echo $line|cut -d, -f1`
        base=`grep $barcode $FILE1`
        full=`grep $barcode $FILE2|awk -F',' '{print $2 "," $3 "," $4 "," $5 "," $6}'`
        echo -ne $base","$full"\n"
done < $FILE1
Wat als je barcode wel in file1 staat, maar niet in file2? Of andersom? Wat als er rare tekens in een productnaam staan? Wat als er extra comma's in de waarde staan?

Verder is $() netter dan ``. Leest makkelijker en is beter met nesting.

Als je meerdere manipulaties wil gaan doen op die data, is het wellicht makkelijker om dit in een sqlite database o.i.d. te steken.

We are pentium of borg. Division is futile. You will be approximated.


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Rainmaker schreef op maandag 14 december 2015 @ 22:03:
[...]


Bash is in de regel juist niet "snel".

Snel is C of C++. Misschien compiled perl.
Een (mooie) tussenvorm is Python. Redelijk snel en redelijk makkelijk te onderhouden. En staat redelijk standaard op ieder Linux systeem. Zeker omdat hier gewoon standaard modules voor bestaan (zoals de hierboven aangegeven blaze, ook al kende ik die zelf nog niet. Maar er is ook een "csv" module. Ander voorbeeld is deze module, waar dit mergen gewoon in de voorbeelden staat).


[...]


Wat als je barcode wel in file1 staat, maar niet in file2? Of andersom? Wat als er rare tekens in een productnaam staan? Wat als er extra comma's in de waarde staan?

Verder is $() netter dan ``. Leest makkelijker en is beter met nesting.

Als je meerdere manipulaties wil gaan doen op die data, is het wellicht makkelijker om dit in een sqlite database o.i.d. te steken.
Ik vond bash toch altijd best snel 8)7 . Goed om te weten dat het nog sneller kan. Met jouw voorbeeld ga ik wel even stoeien.

In de 2de file zal ten alle tijde een EAN code staan aangezien ik die file gemaakt heb met een ander script welke dit allemaal filtert etc. Wel zijn er fabrikant nummer waar dus speciale codes instaan zoals > of <. Voor de rest ben ik eigenlijk nog niet zoveel geks tegen gekomen.

Volgens mij staat er trouwens wel een kleine fout in je script. Ik neem aan dat je met de laatste regel file3 bedoelt ipv file1.

[ Voor 4% gewijzigd door Yagermeister op 15-12-2015 07:59 ]

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Nee, met < voer je iets aan de taak die je erboven hebt gedefinieerd. Wat heb je eraan om file3, die leeg is, regel voor regel te doorlopen? Als er nou > file1 had gestaan, dan was 't wat anders en had je gelijk.

Overigens, mbt snelheid bash, doe eens een 'time' op dingen die je met bash doet en met andere talen dan uitvoeren, zoals python of perl. Dan zie je dat 't echt niet zo snel is als je denkt. Let erop dat 1 seconde voor jou snel is, maar voor een computer best langzaam. En door gebruik te maken van externe tools zoals awk wordt het alleen maar trager vanwege de invocatie. Dat is 'duur' en kost dus tijd, native oplossingen die in python bijvoorbeeld zitten zijn veel sneller en 'goedkoper'.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op dinsdag 15 december 2015 @ 08:32:
Nee, met < voer je iets aan de taak die je erboven hebt gedefinieerd. Wat heb je eraan om file3, die leeg is, regel voor regel te doorlopen? Als er nou > file1 had gestaan, dan was 't wat anders en had je gelijk.

Overigens, mbt snelheid bash, doe eens een 'time' op dingen die je met bash doet en met andere talen dan uitvoeren, zoals python of perl. Dan zie je dat 't echt niet zo snel is als je denkt. Let erop dat 1 seconde voor jou snel is, maar voor een computer best langzaam. En door gebruik te maken van externe tools zoals awk wordt het alleen maar trager vanwege de invocatie. Dat is 'duur' en kost dus tijd, native oplossingen die in python bijvoorbeeld zitten zijn veel sneller en 'goedkoper'.
Ah ik had gemist dat die < stond en dus als invoer diende. Ik zie namelijk nergens waar die naar file3 schrijft.

Op dit moment ben ik nog veel aan het leren dus om nou meteen naar python over te stappen is me een stap te ver. Ik begin nu net pas een beetje met awk rond te komen om daar de dingen in te doen.

Let wel dat alle scripts maar 2 of 3x per dag worden aangeroepen dus een seconde meer of minder maakt nu in het begin heel weinig uit. Zodra ik de basis een beetje onder de knie heb wil ik wel inderdaad gaan kijken naar een betere/snellere oplossing. Dat zal echter nog een paar maanden duren.

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Alles wordt regel voor regel op stdout gegooid. Het script kan je dus aanroepen en dan redirecten naar een bestand. Je kan ook "< file1 > file3" doen. Of na de echo een >> file3. Weet ook het verschil tussen > en >>. Dat mag je zelf gaan uitzoeken. ;)

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op dinsdag 15 december 2015 @ 08:42:
Alles wordt regel voor regel op stdout gegooid. Het script kan je dus aanroepen en dan redirecten naar een bestand. Je kan ook "< file1 > file3" doen. Of na de echo een >> file3. Weet ook het verschil tussen > en >>. Dat mag je zelf gaan uitzoeken. ;)
Ik moet me echt aanleren om niet meer zo vroeg te reageren :z. Nu ik het script nog eens lees is het inderdaad een kwestie van >> file3 achter de awk regel te zetten (append ;)) of > achter de laatste regel om ineens alles erin te tiefen (write ;)).

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Je moet idd niet zo snel reageren, want als je >> achter de awk regel frot, heb je er niets aan. ;)

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • FRidh
  • Registratie: Januari 2004
  • Laatst online: 08:53
Yagermeister schreef op maandag 14 december 2015 @ 20:17:
[...]

[...]


de 2de file heeft maar 1 ean nummer. Alleen de eerste file heeft er meerdere. Het is me inmiddels ook gelukt om deze te joinen middels het join commando. Alleen hapert die op meerdere ean nummers.
Hier nog eentje waarbij `file1_data` cd csv leest, vervolgens de barcodes split, en uiteindelijk een DataFrame teruggeeft.

Dan lezen we het tweede bestand ook in, en doen een merge.
Je kan het ook met Blaze doen (zoals m'n vorige voorbeeld).

Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
file1 = 'file1.csv'
file2 = 'file2.csv'
file3 = 'file3.csv'

import pandas as pd
import csv
import itertools

def file1_data(file1):
    with open(file1, 'r') as fp:
        reader = csv.reader(fp)
        header = next(reader)
        return pd.DataFrame(list(itertools.chain(*(map(lambda x: map((lambda y: (y, x[1])), x[0].split(',')), reader)))), columns=header)

data1 = file1_data(file1)
data2 = pd.read_csv(file2)

pd.merge(data1, data2, how='outer', on='Barcode').to_csv('file3')


edit: en ik denk dat het toch mogelijk moet zijn zonder die lambda's door beter map en zip te gebruiken :) Overigens, als je er een generator functie van maakt is het veel leesbaarder, maar dan krijg je wel twee functies.

[ Voor 9% gewijzigd door FRidh op 15-12-2015 12:10 ]

Research is to see what everybody else has seen, and to think what nobody else has thought - Albert Szent-Györgyi


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op dinsdag 15 december 2015 @ 10:33:
Je moet idd niet zo snel reageren, want als je >> achter de awk regel frot, heb je er niets aan. ;)
Soms zijn er van die dagen dat je beter in bed kunt blijven liggen :+

Om het dan alsnog goed af te ronden, de >> kan op de laatste regel achteraan zodat die daar alles mooi in file3 gooit.

-Te huur


Acties:
  • +1 Henk 'm!

  • Rainmaker
  • Registratie: Augustus 2000
  • Laatst online: 14-07-2024

Rainmaker

RHCDS

Yagermeister schreef op dinsdag 15 december 2015 @ 07:58:
[...]

Ik vond bash toch altijd best snel 8)7 . Goed om te weten dat het nog sneller kan. Met jouw voorbeeld ga ik wel even stoeien.
Bash is een interpreted language, en daarmee automatisch niet snel.
Je hebt eigenlijk 3 soorten programmeertalen:
- Interpreted. Draait binnen een interpreter, zoals bash. Iedere regel wordt door de interpreter bekeken en uitgevoerd
- Compiled. Maakt echte executables. Source moet gecompiled worden en resultaat is een echte .exe of ELF, die direct kunnen worden uitgevoerd.
- Intermediate_representation (Wikipedia: Intermediate language). Script wordt voor het uitvoeren door een compiler-achtige interpreter heen gehaald en wordt uiteindelijk als zgn byte-code uitgevoerd.

Omdat ik ook nog e.e.a. wou proberen met verschillende IDEs, en op zoek was naar een simpel programmaatje om te maken, heb ik het maar eens geprobeerd.

Ik heb eerst een random "csv1" gegenereerd:

code:
1
2
3
for i in {1..10000}; do
for> echo $(uuidgen),$(shuf -n 1 /usr/share/dict/cracklib-small) >> /tmp/csv1.csv
for> done


(dit duurde overigens zo'n 5 minuten)

Hierna een "csv2":
code:
1
2
3
4
cat /tmp/csv1.csv | while read line; do
pipe while> bar=$(echo ${line} | awk -F , '{print $1}')
pipe while> echo ${bar},$(uuidgen),$(uuidgen),1,1 >> /tmp/csv2.csv
pipe while> done


Beide files staan op tmpfs, om te voorkomen dat we hier I/O aan het benchmarken zijn. Ik maak expres geen gebruik van modules, templates o.i.d., anders zijn we hier CSV frameworks aan het benchmarken.

bash:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

starttime=$(date +%s%N)
echo "Started at ${starttime}"

cat /tmp/csv1.csv | while read line; do
    bar=$(echo $line | awk -F , '{print $1}')
    fullinfo=$(grep "${bar}" /tmp/csv2.csv)
    echo ${line},$(echo "${fullinfo}" | cut --complement -d ',' -f 1) >> /tmp/csv3.csv
done

endtime=$(date +%s%N)
echo "Done at ${endtime}"

echo "Time taken $(expr ${endtime} - ${starttime}) nanoseconds"


Resultaat:
./tweak.sh
Started at 1451337274579537852
Done at 1451337427989920823
Time taken 153410382971 nanoseconds
153 seconden, of ~ 2.5 minuten

Python
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from time import time

starttime = time()
print("Started at {}".format(starttime))

f1 = open('/tmp/csv1.csv')
f2 = open('/tmp/csv2.csv')
f3 = open('/tmp/csv3python.csv', mode='w')

for line in f1:
    barcode = line.split(',')[0]

    for fullline in f2:
        if fullline.startswith(barcode):
            extrainfo = fullline[fullline.index(',') + 1:]
            newline = '{},{}'.format(line.strip('\n'), extrainfo)

    f2.seek(0)
    f3.write('{}'.format(newline))

endtime = time()
print('Done at {}'.format(endtime))

print('Taken {} seconds'.format(endtime-starttime))


Resultaat:
Started at 1451338532.7614973
Done at 1451338651.3239393
Taken 118.56244206428528 seconds
118 seconden, net geen 2 minuten.

C++
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <chrono>

int main() {
    auto starttime = std::chrono::high_resolution_clock::now();

    std::ifstream f1("/tmp/csv1.csv");
    std::ifstream f2("/tmp/csv2.csv");
    std::ofstream f3("/tmp/csv3cplusplus.csv");

    std::string f1_line;
    std::string f2_line;
    std::string newline;

    while(std::getline(f1, f1_line)) {
        std::string barcode = f1_line.substr(0, f1_line.find(','));

        //Find barcode in f2
        f2.clear();
        f2.seekg(0);
        while(std::getline(f2, f2_line)) {
            // Check if barcode is at start of line
            if(f2_line.find(barcode) == 0) {
                newline = f1_line + "," + f2_line.substr(f2_line.find(',') + 1);
            }
        }

        f3 << newline;
    }

    f3.close();
    auto endtime = std::chrono::high_resolution_clock::now();
    std::cout << "Program finished in " <<
            std::chrono::duration_cast <std::chrono::nanoseconds> (endtime-starttime).count() <<
            " nanoseconds\n";

    return 0;
}


Resultaat:
Program finished in 18621363489 nanoseconds
18.6 seconden. Een factor 7 sneller. Dit kan natuurlijk fluctueren afhankelijk van de workload.

Ondanks dat het dus wel het meest ingewikkeld is, zeker als je met grote datasets moet gaan werken, kan het het zeker waard zijn om een "echt" programma te schrijven.

We are pentium of borg. Division is futile. You will be approximated.


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Rainmaker schreef op maandag 28 december 2015 @ 23:45:
[...]


Bash is een interpreted language, en daarmee automatisch niet snel.
Je hebt eigenlijk 3 soorten programmeertalen:
- Interpreted. Draait binnen een interpreter, zoals bash. Iedere regel wordt door de interpreter bekeken en uitgevoerd
- Compiled. Maakt echte executables. Source moet gecompiled worden en resultaat is een echte .exe of ELF, die direct kunnen worden uitgevoerd.
- Intermediate_representation (Wikipedia: Intermediate language). Script wordt voor het uitvoeren door een compiler-achtige interpreter heen gehaald en wordt uiteindelijk als zgn byte-code uitgevoerd.

Omdat ik ook nog e.e.a. wou proberen met verschillende IDEs, en op zoek was naar een simpel programmaatje om te maken, heb ik het maar eens geprobeerd.

Ik heb eerst een random "csv1" gegenereerd:

code:
1
2
3
for i in {1..10000}; do
for> echo $(uuidgen),$(shuf -n 1 /usr/share/dict/cracklib-small) >> /tmp/csv1.csv
for> done


(dit duurde overigens zo'n 5 minuten)

Hierna een "csv2":
code:
1
2
3
4
cat /tmp/csv1.csv | while read line; do
pipe while> bar=$(echo ${line} | awk -F , '{print $1}')
pipe while> echo ${bar},$(uuidgen),$(uuidgen),1,1 >> /tmp/csv2.csv
pipe while> done


Beide files staan op tmpfs, om te voorkomen dat we hier I/O aan het benchmarken zijn. Ik maak expres geen gebruik van modules, templates o.i.d., anders zijn we hier CSV frameworks aan het benchmarken.

bash:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#!/bin/bash

starttime=$(date +%s%N)
echo "Started at ${starttime}"

cat /tmp/csv1.csv | while read line; do
    bar=$(echo $line | awk -F , '{print $1}')
    fullinfo=$(grep "${bar}" /tmp/csv2.csv)
    echo ${line},$(echo "${fullinfo}" | cut --complement -d ',' -f 1) >> /tmp/csv3.csv
done

endtime=$(date +%s%N)
echo "Done at ${endtime}"

echo "Time taken $(expr ${endtime} - ${starttime}) nanoseconds"


Resultaat:

[...]


153 seconden, of ~ 2.5 minuten

Python
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from time import time

starttime = time()
print("Started at {}".format(starttime))

f1 = open('/tmp/csv1.csv')
f2 = open('/tmp/csv2.csv')
f3 = open('/tmp/csv3python.csv', mode='w')

for line in f1:
    barcode = line.split(',')[0]

    for fullline in f2:
        if fullline.startswith(barcode):
            extrainfo = fullline[fullline.index(',') + 1:]
            newline = '{},{}'.format(line.strip('\n'), extrainfo)

    f2.seek(0)
    f3.write('{}'.format(newline))

endtime = time()
print('Done at {}'.format(endtime))

print('Taken {} seconds'.format(endtime-starttime))


Resultaat:

[...]


118 seconden, net geen 2 minuten.

C++
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <chrono>

int main() {
    auto starttime = std::chrono::high_resolution_clock::now();

    std::ifstream f1("/tmp/csv1.csv");
    std::ifstream f2("/tmp/csv2.csv");
    std::ofstream f3("/tmp/csv3cplusplus.csv");

    std::string f1_line;
    std::string f2_line;
    std::string newline;

    while(std::getline(f1, f1_line)) {
        std::string barcode = f1_line.substr(0, f1_line.find(','));

        //Find barcode in f2
        f2.clear();
        f2.seekg(0);
        while(std::getline(f2, f2_line)) {
            // Check if barcode is at start of line
            if(f2_line.find(barcode) == 0) {
                newline = f1_line + "," + f2_line.substr(f2_line.find(',') + 1);
            }
        }

        f3 << newline;
    }

    f3.close();
    auto endtime = std::chrono::high_resolution_clock::now();
    std::cout << "Program finished in " <<
            std::chrono::duration_cast <std::chrono::nanoseconds> (endtime-starttime).count() <<
            " nanoseconds\n";

    return 0;
}


Resultaat:

[...]


18.6 seconden. Een factor 7 sneller. Dit kan natuurlijk fluctueren afhankelijk van de workload.

Ondanks dat het dus wel het meest ingewikkeld is, zeker als je met grote datasets moet gaan werken, kan het het zeker waard zijn om een "echt" programma te schrijven.
Hulde voor deze hele lap tekst. Ik heb het eens doorgelezen en het ziet er zeer interessant uit. Er zijn echter een paar maartjes wat me tegenhouden op dit moment.

de grootste leverancier heeft een file van bijna 200mb met daarin bijna 500k aan regels. Als ik alle onnodige data eruit gooi zoals links en beschrijvingen blijft er een file over van een 25mb. Als ik daarvan het script uitvoer zoals ik het geschreven heb op dit moment (zie hieronder) dan doe ik daar ongeveer een 35 seconden op waarbij de meeste tijd in het downloaden zit (ongeveer een 30 sec). Dit is voor ons doen prima te verhappen aangezien dit een leverancier is wat we maar 1x per dag inladen en dan ook nog eens niet actief gebruiken.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/sh
PAD='/srv/prijslijst/leverancier'
ARCHIEF='/srv/prijslijst/archief/leverancier'
DATUM=$(date +"%Y%m%d")
TIJDDATUM=$(date +"%Y%m%d_%H%M%S")

#############################
## Alle Email instellingen ##
#############################

SUBJECT="Prijslijst leverancier"
TO="mezelf"
MESSAGE="/tmp/message.txt"

echo "Prijslijst leverancier geupdate" >> $MESSAGE
echo "Time: $TIJDDATUM" >> $MESSAGE
############################

wget -q http://csv.zip -O $PAD/csv.zip

unzip -o $PAD/csv.zip -d $PAD

cut -f1,4-6,8,12,13 $PAD/csv.txt > $PAD/raw.csv

## In verband met de grootte van de file alleen de correcte kolommen backuppen
cp $PAD/raw.csv $ARCHIEF/origineel.$TIJDDATUM.csv

awk '!/^\t|\t\t|\t$/' $PAD/raw.csv > $PAD/raw2.csv

awk 'BEGIN { FS="\t"; OFS=";"; } { print $2,$1,$4,$6 + $7,$5,$3; }' $PAD/raw2.csv > $PAD/raw3.csv

awk '{if (NR!=1) {print}}' $PAD/raw3.csv > $PAD/clean.csv

## Maak een backup van de cleane file
cp $PAD/clean.csv $ARCHIEF/upload.$TIJDDATUM.csv

tar -cvzf /tmp/leverancier.tar.gz $ARCHIEF/origineel.$TIJDDATUM.csv $ARCHIEF/upload.$TIJDDATUM.csv

cat $MESSAGE | /usr/bin/mutt -s "$SUBJECT" -a /tmp/leverancier.tar.gz -- $TO

rm /tmp/leverancier.tar.gz
rm /tmp/message.txt
rm $PAD/*


Alle andere leveranciers hebben een kortere versie waarvan het draaien ongeveer een 3 tot 4 seconden duurt maximaal. De meeste hebben zelfs maar maximaal 100k aan regels erin zitten.

Van het hele scripting heb ik minimale ervaring waarmee bovenstaande wel allemaal prima gelukt is. Zoals bovenstaande personen ook al aangeven zou het beter zijn om dit zelfs in python te doen waarmee ik ondertussen al minimaal aan de slag ben gegaan bij een andere leverancier omdat het toevallig goed uitkwam daar. De toolkit die ik daarvoor gebruik is overigs te vinden hier.

Nu ben ik wel van plan om het geheel om te zetten naar python maar dat zal nog wel even duren omdat ik gewoonweg geen ervaring in python heb.

Ondertussen ben ik ook zover dat ik bij de leverancier met de meerdere ean codes ook uitgevonden heb hoe ik die het beste kan filteren indien er minder dan de 6 barcodes zijn. Dit heb ik simpel opgelost door een if then else oplossing te gebruiken (zie hieronder)

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
awk 'BEGIN { FS="\;"; OFS=";"; } {
        if ($5 == "")
                print $4,$1,$3,$11,$10,$2;
        else if ($6 == "")
                print $4","$5,$1,$3,$11,$10,$2;
        else if ($7 == "")
                print $4","$5","$6,$1,$3,$11,$10,$2;
        else if ($8 == "")
                print $4","$5","$6","$7,$1,$3,$11,$10,$2;
        else if ($9 == "")
                print $4","$5","$6","$7","$8,$1,$3,$11,$10,$2;
        else
                print $4","$5","$6","$7","$8","$9,$1,$3,$11,$10,$2;
        }
' $PAD/raw3.csv > $PAD/raw4.csv


Dit is misschien niet de meest elegante oplossing maar het werkt wel.

Nu moet ik alleen nog even met de eerdere suggesties het samenvoegen van de bestanden doen waarbij beide bestanden ook nog eens meerdere ean codes kunnen bevatten. Dit was eerst gedacht dat er maar 1 aan onze kant uitgespuugd werd maar dit is blijkbaar toch alle die in het product staan. Hiervoor wil ik gaan kijken naar de oplossing die Donaldinho aangaf aangezien dat voor mij de meest herkenbare/makkelijkste oplossing is.

Als iemand een andere/makkelijkere oplossing heeft hiervoor dan hoor ik het graag.

Betreffende het python verhaal ben ik nu wel bezig met een aantal test scripts maar helaas zit ik wat krap in de tijd om hier veel aan te werken omdat bovenstaande nog niet 100% is. Om naar C++ te gaan kijken lijkt mij op dit moment nog wat erg extreem. Daarbij denk ik niet dat de winst zo groot zal zijn gezien de doorlooptijden op dit moment.

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Om het awk gedeelte wat beter te doen, zoek eerst uit welk veld $NF is, dan kan je gerichter te werk gaan. Want wat doe je als veld 5 leeg is, maar 6 toch is gevuld omdat er ergens iets is vergeten neer te zetten?

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op dinsdag 29 december 2015 @ 23:22:
Om het awk gedeelte wat beter te doen, zoek eerst uit welk veld $NF is, dan kan je gerichter te werk gaan. Want wat doe je als veld 5 leeg is, maar 6 toch is gevuld omdat er ergens iets is vergeten neer te zetten?
Je hebt gelijk echter moet ik die functie nog uitzoeken. Wel is het zo dat veld 5 niet leeg kan zijn en veld 6 gevuld. De velden 4 t/m 9 zijn namelijk op een volgend ean 1 t/m 6. Daarbij wordt er van tevoren al gefilterd op veld 4 indien deze leeg is. Als deze leeg is wordt die regel verwijderd.

Stel nu echter dat het toch onverhoopt zou voorkomen dan is de regel ipv EAN1,EAN2,EAN3;SKU_LEV;SKU_FAB;ETC -> EAN1,,;SKU_LEV;SKU_FAB;ETC

Ja het is wat minder netjes en er is een kleine kans dat er een EAN missend is maar om mee te starten mag dat het probleem niet zijn. Alles wordt toch gecontroleerd zodra het ingeladen is. Zodra de tijd het toelaat wil ik me richten op python om de scripts daarin om te zetten om zoals jullie al aangeven tijd te besparen wegens de snelheid.

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Snelheid is suggestief. Als je script handmatig gestart wordt, kan een seconde heel wat zijn, maar als het via een cron job gaat, is het niet zo boeiend IMO. Tenzij je iets anders dat erna draait echt op de seconde of korter zit te wachten. Maar je gaf zelf al aan dat bij eentje het downloaden al 95% van de tijd in beslag nam.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op woensdag 30 december 2015 @ 11:58:
Snelheid is suggestief. Als je script handmatig gestart wordt, kan een seconde heel wat zijn, maar als het via een cron job gaat, is het niet zo boeiend IMO. Tenzij je iets anders dat erna draait echt op de seconde of korter zit te wachten. Maar je gaf zelf al aan dat bij eentje het downloaden al 95% van de tijd in beslag nam.
Alle lijsten gaan inderdaad via een cronjob die steeds 5min ruimte tussen elk script in laat. Dit werkt prima behalve dat ik een tering bende aan mail binnen krijg :P. Dit laatste is echter puur ter controle.

Zoals eerder al aangegeven is het enigste waar ik nu mee in de knoei hang de meerdere ean nummers combineren in 2 files.

Ik heb bovenstaande code van Donaldinho al geprobeerd maar deze verslikt zich met meerdere ean's in file 1. Die regels geeft hij een foutmelding aan waar ik nog niet uit ben. Onderstaand is stuk waarop die gelopen heeft.

Dit is overigens alleen in File 1 een meerdere EAN codes. Met beide files meerdere codes krijg ik hetzelfde.

Regel 1 is een correcte samenvoeging van beide files.
Regel 2 is een nep code die hij negeert/niet vindt.
Daaronder de foutmeldingen dat hij dit niet accepteert. Deze nep code heb ik voor de zekerheid ook in de andere file gezet zodat hij hem zou moeten meenemen.

Daarbij zou hij de niet gecombineerde regels liever moeten weglaten alhoewel dat niet echt een vereiste is.
code:
1
2
3
4
5
6
7
8
9
Barcode;Sku,
4960999865300;testnderp,123445,654321,0,500,00,TEST
1230000000008;ND008,
grep: 1240000000009: No such file or directory
grep: 1240000000009: No such file or directory
/srv/prijslijst/website/clean1.csv:1230000000009, 1240000000009;ND009,
grep: 1240000000010: No such file or directory
grep: 1240000000010: No such file or directory
/srv/prijslijst/website/clean1.csv:1230000000010, 1240000000010;ND010,



Nu had ik wel onderstaande code eens geprobeert echter negeert deze ook doodleuk de meerdere ean codes in file 1. Ik heb dit wel nog niet getest met meerdere eans in file 1 en 2 maar ik gok dat die ook daar dit gewoon negeert.

code:
1
awk -F";" -v OFS=";", 'NR==FNR{a[$1]=$2; next}{print $0";"a[$1]}' website/clean1.csv archief/lev/upload.20151230_004001.csv

[ Voor 26% gewijzigd door Yagermeister op 30-12-2015 12:14 ]

-Te huur


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Bump. Hopelijk weet iemand een oplossing voor de meerdere ean nummers per file.

-Te huur


Acties:
  • 0 Henk 'm!

  • CAPSLOCK2000
  • Registratie: Februari 2003
  • Laatst online: 16-07 10:55

CAPSLOCK2000

zie teletekst pagina 888

Ik denk dat er geen kant-en-klare oplossing is, ik vrees dat het vooral een kwestie is van stug doorprgrammeren. Het lukt vast wel met bash maar ik betwijfel of het de makkelijkste manier is. Als het je om het leerproces gaat dan moet je vooral je gang gaan maar als je snel naar een oplossing toe wil kun je beter met een wat modernere script-taal werken (je ben nu al 50% in AWK aan het doen ;)

This post is warranted for the full amount you paid me for it.


Acties:
  • 0 Henk 'm!

  • begintmeta
  • Registratie: November 2001
  • Niet online

begintmeta

Moderator General Chat
Hoezeer ik het niet willen installeren van 'aanvullende software' ook begrijp, is te stevig daaraan vasthouden toch ook vaak niet heel verstandig. (Vandaar dat ik je ook een uitweg (uitvlucht) wilde bieden, wat is nou eigenlijk 'aanvullende software'? (je kan eventueel ook van bash overstappen op lisp als shell >:) ))

[ Voor 49% gewijzigd door begintmeta op 04-01-2016 18:29 ]


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
begintmeta schreef op maandag 04 januari 2016 @ 18:23:
Hoezeer ik het niet willen installeren van 'aanvullende software' ook begrijp, is te stevig daaraan vasthouden toch ook vaak niet heel verstandig. (Vandaar dat ik je ook een uitweg (uitvlucht) wilde bieden, wat is nou eigenlijk 'aanvullende software'? (je kan eventueel ook van bash overstappen op lisp als shell >:) ))
CAPSLOCK2000 schreef op maandag 04 januari 2016 @ 18:18:
Ik denk dat er geen kant-en-klare oplossing is, ik vrees dat het vooral een kwestie is van stug doorprgrammeren. Het lukt vast wel met bash maar ik betwijfel of het de makkelijkste manier is. Als het je om het leerproces gaat dan moet je vooral je gang gaan maar als je snel naar een oplossing toe wil kun je beter met een wat modernere script-taal werken (je ben nu al 50% in AWK aan het doen ;)
Op zich wil ik het liefste bij de standaard tools blijven maar als dat geen simpele oplossing zou bieden door teveel hang en sluit werk zou ik natuurlijk gek zijn als ik niet ook naar andere oplossingen kijk. Het enigste nadeel voor mij zelf is dat ik weinig tot geen verstand dan heb van de code en ik dan puur afhankelijk ben van de informatie die gegeven wordt. Dat is juist de reden waarom ik het zoveel mogelijk probeer te vermijden.

Nogmaals als iemand een simpele oplossing heeft in een andere taal sta ik hier zeker voor open. Wel is het voor mij dan even handig als er een kleine/korte uitleg bijstaat van de code zodat ik deze ook kan begrijpen.

Ik heb trouwens beide cvskit en csvtools geinstalleerd maar ook daarmee lukt het me niet om te joinen.

[ Voor 3% gewijzigd door Yagermeister op 04-01-2016 19:03 ]

-Te huur


Acties:
  • 0 Henk 'm!

  • FRidh
  • Registratie: Januari 2004
  • Laatst online: 08:53
Yagermeister schreef op maandag 04 januari 2016 @ 11:19:
Bump. Hopelijk weet iemand een oplossing voor de meerdere ean nummers per file.
Mijn tweede oplossing werkt met meerdere EAN nummers, maar heeft wel flink wat dependencies.
Ik denk dat het ook wel snel zal zijn, echter, in deze oplossing wordt alle data ingeladen en dus kan het problematisch zijn als je een groot bestand heb.

Met de volgende implementatie heb je dat probleem niet (getest met Python 3.5).
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import csv

def merger(file1, file2, file3, dialect='unix'):
    """Read file1, split barcodes and yield each new row"""
    with open(file1, 'r') as fp1, open(file2, 'r') as fp2, open(file3, 'w') as fp3:
        f1reader = csv.reader(fp1, dialect=dialect)
        f2reader = csv.reader(fp2, dialect=dialect)
        f3writer = csv.writer(fp3, dialect=dialect)
        
        # Write header to file
        f3writer.writerow(['Barcode', 'Sku_Eigen', 'Sku_Lev', 'Sku_Fab', 'Inkoop', 'Verkoop'])
        # Skip header when reading
        next(f1reader) 
        
        for Barcode, Sku_Eigen in f1reader:
            for unique_barcode in Barcode.split(', '):
                fp2.seek(0) # Rewind file pointer
                next(f2reader) # Skip header
                for row in f2reader:
                    if unique_barcode == row[0]:
                        out = [unique_barcode, Sku_Eigen] + row[2:]
                        f3writer.writerow(out)
                        break

merger(file1, file2, file3)

Research is to see what everybody else has seen, and to think what nobody else has thought - Albert Szent-Györgyi


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
FRidh schreef op maandag 04 januari 2016 @ 23:02:
[...]


Mijn tweede oplossing werkt met meerdere EAN nummers, maar heeft wel flink wat dependencies.
Ik denk dat het ook wel snel zal zijn, echter, in deze oplossing wordt alle data ingeladen en dus kan het problematisch zijn als je een groot bestand heb.

Met de volgende implementatie heb je dat probleem niet (getest met Python 3.5).
Python:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import csv

def merger(file1, file2, file3, dialect='unix'):
    """Read file1, split barcodes and yield each new row"""
    with open(file1, 'r') as fp1, open(file2, 'r') as fp2, open(file3, 'w') as fp3:
        f1reader = csv.reader(fp1, dialect=dialect)
        f2reader = csv.reader(fp2, dialect=dialect)
        f3writer = csv.writer(fp3, dialect=dialect)
        
        # Write header to file
        f3writer.writerow(['Barcode', 'Sku_Eigen', 'Sku_Lev', 'Sku_Fab', 'Inkoop', 'Verkoop'])
        # Skip header when reading
        next(f1reader) 
        
        for Barcode, Sku_Eigen in f1reader:
            for unique_barcode in Barcode.split(', '):
                fp2.seek(0) # Rewind file pointer
                next(f2reader) # Skip header
                for row in f2reader:
                    if unique_barcode == row[0]:
                        out = [unique_barcode, Sku_Eigen] + row[2:]
                        f3writer.writerow(out)
                        break

merger(file1, file2, file3)
Ik heb bovenstaande even geprobeerd maar hij jammert erover dat die de csv module niet kan vinden. Ik draai versie 2.7.9 (Debian install) maar dat zou het probleem niet mogen zijn. Wel heb ik zelf nog wat verder zitten te zoeken en ben onderstaande awk one-liner tegen gekomen:

awk -F"[,|;]" 'FNR==NR{A[$1]=$0;next} ($1 in A){q=$1;sub($1,X);print A[q] $0}' file1.csv file2.csv > merged.csv

Deze lijkt te werken zoals wij dat nodig hebben. Ik weet wel nog niet alle details wat het script precies doet maar we kunnen in ieder geval vooruit. Bedankt in ieder geval voor alle hulp.

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Heb je wel python-csvkit geïnstalleerd? Standaard issie namelijk dat niet. De omschrijving:
csvkit is a suit of utilities for converting to and working with CSV, the king of tabular file formats.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Ik heb csvkit en ook csvtools geinstalleerd omdat ik beide ook gebruik bij 1 van de scripts.

-Te huur


Acties:
  • 0 Henk 'm!

  • Hero of Time
  • Registratie: Oktober 2004
  • Laatst online: 17:02

Hero of Time

Moderator LNX

There is only one Legend

Je weet wel dat python-csvkit voor Python 2 is, en niet voor Python 3? Die heeft een andere package.

Commandline FTW | Tweakt met mate


Acties:
  • 0 Henk 'm!

  • FRidh
  • Registratie: Januari 2004
  • Laatst online: 08:53
Yagermeister schreef op dinsdag 05 januari 2016 @ 12:02:
[...]


Ik heb bovenstaande even geprobeerd maar hij jammert erover dat die de csv module niet kan vinden. Ik draai versie 2.7.9 (Debian install) maar dat zou het probleem niet mogen zijn.
Ik gebruikte de built-in csv module, welke beschikbaar is voor zowel Python 2.x als 3.x.

Research is to see what everybody else has seen, and to think what nobody else has thought - Albert Szent-Györgyi


Acties:
  • 0 Henk 'm!

  • Yagermeister
  • Registratie: December 2001
  • Laatst online: 15:09

Yagermeister

Bedrijfsprutser on call

Topicstarter
Hero of Time schreef op dinsdag 05 januari 2016 @ 15:50:
Je weet wel dat python-csvkit voor Python 2 is, en niet voor Python 3? Die heeft een andere package.
Ik heb ook Python 2.7.9 zoals eerder aangegeven. De CSV module zou echter al in python moeten zitten en door middel van de import csv zou die aangeroepen moeten kunnen worden.

-Te huur

Pagina: 1