Parsování CSV pomocí AWK

M

Parsování CSV pomocí AWK
« kdy: 14. 08. 2017, 14:13:03 »
Ahoj,

Rád bych vás tu požádal o pomoc.

Potřebuji rozparsovat csv soubor pomocí awk.
Jednotlivé sloupce jsou odděleny ;
String v jednotlivých sloupcích obsahuje mezery.

Kód: [Vybrat]
awk -F";" '{print $1":"$2":"$3}' mi bohužel s mezerami nefunguje.

Příklad mého CSV.
Kód: [Vybrat]
sloupec1 s mezerami;sloupec2;Sloupec3 s mezerami

Předem díky za radu :)
« Poslední změna: 14. 08. 2017, 20:43:54 od Petr Krčmář »


Tuxik

  • *****
  • 1 473
    • Zobrazit profil
    • E-mail
Re:AWK - CSV Parsing
« Odpověď #1 kdy: 14. 08. 2017, 14:45:37 »
Zvláštní...

Kód: [Vybrat]
# awk -F";" '{print $1":"$2":"$3}' test.csv
sloupec1 s mezerami:sloupec2:Sloupec3 s mezerami

mně to normálně funguje...

Kód: [Vybrat]
# awk --version
GNU Awk 4.1.0, API: 1.0

Tomas2

  • ****
  • 310
    • Zobrazit profil
    • E-mail
Re:AWK - CSV Parsing
« Odpověď #2 kdy: 14. 08. 2017, 18:48:34 »
pokud máš awk 3, mělo by ti fungovat

Kód: [Vybrat]
awk 'BEGIN { FS=";" } {print $1":"$2":"$3}'

mikrom

Re:Parsování CSV pomocí AWK
« Odpověď #3 kdy: 14. 08. 2017, 21:31:02 »
Okrem FS(=Field Separator) je mozne definovat aj OFS (=output FS). Potom sa to da takto:
  awk 'BEGIN{FS=";";OFS=":"} {print $1,$2,$3}' my_file.csv
alebo
  awk -F';' 'BEGIN{FS=";";OFS=":"} {print $1,$2,$3}' my_file.csv
 

M

Re:Parsování CSV pomocí AWK
« Odpověď #4 kdy: 15. 08. 2017, 09:40:37 »
Díky všem za odpovědi!
Máte pravdu. AWK (GNU Awk 3.1.8) funguje a rozhází se mi to až v následné iteraci, což jsem nepředpokládal.


Kód: [Vybrat]
OPTIONS=`cat $SOURCE_LIST | awk -F";" 'NR>1 {print $1":"$2":"$3}'`

X=0
for LINES in $OPTIONS
do
X=$((X+1))
CHOICE[$X]=`echo $LINES`
echo $X "=" ${CHOICE[${X}]}
done


Zdrojové testovací řádky vypadají takto:
Kód: [Vybrat]
Schema full exp;/vymyslena/cesta.sh;Fu ll
D Bfu lle xp;/vymyslena/cesta2.sh;DD BB


Kód: [Vybrat]
A dostávám:
Kód: [Vybrat]
1 = Schema
2 = full
3 = exp:/vymyslena/cesta.sh:Fu
4 = ll
5 = D
6 = Bfu
7 = lle
8 = xp:/vymyslena/cesta2.sh:DD
9 = BB


Tomas2

  • ****
  • 310
    • Zobrazit profil
    • E-mail
Re:Parsování CSV pomocí AWK
« Odpověď #5 kdy: 15. 08. 2017, 10:21:47 »
for in v bashi má jako výchozí oddělovač i mezery, musíš ho nastavit pouze na zalomení řádku. Tj.


Kód: [Vybrat]
OPTIONS=`cat $SOURCE_LIST | awk -F";" 'NR>1 {print $1":"$2":"$3}'`

X=0
IFS=$'\n'
for LINES in $OPTIONS
do
X=$((X+1))
CHOICE[$X]=`echo $LINES`
echo $X "=" ${CHOICE[${X}]}
done
X=0

Pokud ale chceš vybrat ze souboru konkrétní řádek, je na to lepší třeba sed a rovnou můžeš jen ten jeden řádek prohnat awk. S tím NF nevím co děláš
Kód: [Vybrat]
sed -n $((X+1)),$((X+1))p $SOURCE_LIST | awk -F";" '{print $1":"$2":"$3}'

Případně to celé můžeš rovnou napsat v awk
Kód: [Vybrat]
X=0
cat $SOURCE_LIST | awk -v X="$X" -F";" 'NR == X+1 {print X+1" = "$1":"$2":"$3}'

Je ale otázka co řešíš, nejspíš to lze udělat daleko čištěji a stabilněji, stačí když sem popíšeš celý problém a nebudeš to kouskovat :)

mikrom

Re:Parsování CSV pomocí AWK
« Odpověď #6 kdy: 15. 08. 2017, 10:57:27 »
rozparsovat jednotlive polia z CSV mozes rovno v awk, nemusis nato pouzivat dodatocne bash.
Kód: [Vybrat]
BEGIN {
  FS=";"
  # init array
  delete words
  n = 0
}
{
  # add field to array
  for(i=1; i<=NF; i++) {
    words[++n] = $i
  }
}

END {
  # print results
  for (i=1; i<=n; i++) {
    printf("%d --> %s\n", i, words[i])
  }
}

po sputeni je vysledok
Kód: [Vybrat]
$ awk -f m.awk m.csv

1 --> Schema full exp
2 --> /vymyslena/cesta.sh
3 --> Fu ll
4 --> D Bfu lle xp
5 --> /vymyslena/cesta2.sh
6 --> DD BB

M

Re:Parsování CSV pomocí AWK
« Odpověď #7 kdy: 15. 08. 2017, 10:59:16 »
@Tomas2 - Díky! Problém vyřešen nastavením oddělovače na zalomení řádku.
Kód: [Vybrat]
IFS=$'\n'
Celá myšlenka je následující.
Jde o interní řešení, kde máme několik bashových scriptů na jednotlivé úkony a vytvářím jakési centrální rozhraní, které načte všechny řádky s cestou, description a pod z csv a následně poskytne výběr, který úkon/script vykonat (proto potřebuji ten cyklus).
Pro základní činnosti tak vznikne lepší zastupitelnost.