Fórum Root.cz

Hlavní témata => Vývoj => Téma založeno: M kdy 14. 08. 2017, 14:13:03

Název: Parsování CSV pomocí AWK
Přispěvatel: M 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.

awk -F";" '{print $1":"$2":"$3}' mi bohužel s mezerami nefunguje.

Příklad mého CSV.
sloupec1 s mezerami;sloupec2;Sloupec3 s mezerami


Předem díky za radu :)
Název: Re:AWK - CSV Parsing
Přispěvatel: Tuxik kdy 14. 08. 2017, 14:45:37
Zvláštní...

# awk -F";" '{print $1":"$2":"$3}' test.csv
sloupec1 s mezerami:sloupec2:Sloupec3 s mezerami


mně to normálně funguje...

# awk --version
GNU Awk 4.1.0, API: 1.0
Název: Re:AWK - CSV Parsing
Přispěvatel: Tomas2 kdy 14. 08. 2017, 18:48:34
pokud máš awk 3, mělo by ti fungovat

awk 'BEGIN { FS=";" } {print $1":"$2":"$3}'
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: mikrom 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
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: M 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.


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:
Schema full exp;/vymyslena/cesta.sh;Fu ll
D Bfu lle xp;/vymyslena/cesta2.sh;DD BB



A dostávám:
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

Název: Re:Parsování CSV pomocí AWK
Přispěvatel: Tomas2 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.



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áš

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

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 :)
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: mikrom kdy 15. 08. 2017, 10:57:27
rozparsovat jednotlive polia z CSV mozes rovno v awk, nemusis nato pouzivat dodatocne bash.

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

$ 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
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: M kdy 15. 08. 2017, 10:59:16
@Tomas2 - Díky! Problém vyřešen nastavením oddělovače na zalomení řádku. 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.