Fórum Root.cz

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

Název: Parsování CSV pomocí AWK
Přispěvatel: M 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 :)
Název: Re:AWK - CSV Parsing
Přispěvatel: Tuxik 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
Název: Re:AWK - CSV Parsing
Přispěvatel: Tomas2 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}'
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: mikrom 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 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
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: Tomas2 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 :)
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: mikrom 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
Název: Re:Parsování CSV pomocí AWK
Přispěvatel: M 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.