Parsing d'un fichier

Bonjour j’aimerais récupérer le nom et prénom mais je n’y arrive pas
'{ firstName : bob , lastName : obb , sometext:[ sometxt , picture ],picture :{ image },{ firstName : alice , lastName : ecila , sometext:[ sometxt , picture ], picture :{ image }, sometext },'

j’ai utiliser sed awk grep mais je n’arrive pas
j’ai essayé cat monfichier | grep -o ‘firstName :.*’ et plein d’autre combinaison
j’ai essayé d’utiliser les motifs avec grep et awk
je ne vois pas par quel bout le prendre

La première étape pour se faciliter le boulot est de découper le fichier en plusieurs lignes, pour ensuite manipuler les lignes indépendamment :

dave@HAL9000:~$ string='{ firstName : bob , lastName : obb , sometext:[ sometxt , picture ],picture :{ image },{ firstName : alice , lastName : ecila , sometext:[ sometxt , picture ], picture :{ image }, sometext },'
dave@HAL9000:~$ echo $string | sed 's/,/\n/g' | while read line; do if [ -n "$(echo $line | grep firstName)" ]; then echo "Prénom :" && echo $line | cut -d':' -f2; elif [ -n "$(echo $line | grep lastName)" ]; then echo "Nom :" && echo $line | cut -d':' -f2; fi; done
Prénom :
 bob
Nom :
 obb
Prénom :
 alice
Nom :
 ecila

beurk.

rgx='Name : (.*)'
while read -d ',' p
do
   [[ $p =~ $rgx ]] && printf '%s\n' "${BASH_REMATCH[1]}"
done <<<"'{ firstName : bob , lastName : obb , sometext:[ sometxt , picture ],picture :{ image },{ firstName : alice , lastName : ecila , sometext:[ sometxt , picture ], picture :{ image }, sometext },'" 

ou

sed 's/,/\n/g' <<<"'{ firstName : bob , lastName : obb , sometext:[ sometxt , picture ],picture :{ image },{ firstName : alice , lastName : ecila , sometext:[ sometxt , picture ], picture :{ image }, sometext },'" \
 | grep -Po 'Name : \K.*'

Si la structure des données ne change pas:

awk -F" [,:] " '{print $2,$4}' fichier

mais cela ne traite que les deux premiers champs; on ne récupère pas “alice”.

Effectivement. Voici donc:

awk 'BEGIN{FS=" [,:] ";RS="},{"}{print $2,$4}' fichier

Ou, de manière plus claire:

awk  '
BEGIN{
   FS=" [,:] "
   RS="},{"
}
{
   print $2,$4
}' fichier
1 J'aime

Dites voir les spécialistes, vous auriez une source ou deux à me conseiller pour me renseigner sur la syntaxe de awk ? :wink:

Jusqu’ici je ne m’en sers que très basiquement, mais il pourrait m’être très pratique si je le connaissais mieux.

Deux liens parmi de nombreux tuto:


https://www.gnu.org/software/gawk/manual/gawk.html

Le mieux est de jouer avec des fichiers et de commencer par coder en indentant proprement le code pour la lisibilité. Les one-liner seront pour plus tard.

Ce langage reste ce qui se fait de mieux pour le traitement de (très) gros fichiers. Du moins en interprété. J’ai fait quelques benchmark entre awk et un compilé (golang) et même si golang était plus rapide, awk n’avait pas à rougir de ses performances.

Juste pour être complet, j’ai retrouvé mon benchmark.

Fichier
SERVER573,13380,3962,21165
SERVER887,20583,20666,1776
SERVER897,7849,3260,10688
SERVER420,20060,7502,27989
SERVER275,884,22932,10301
SERVER221,2203,3556,2530
SERVER882,14405,24151,20245
SERVER370,17678,12059,10055

Voir ici comment générer un tel fichier de 600000 lignes.

Imaginons que l’on cherche à additionner les chiffres de la deuxième colonne (taille RAM par exemple) pour le SERVER788.

AWK

awk -F, '
/^SERVER788/{somme += $2}
END{print somme}
' sample.csv

Go (attention c’est verbeux!)

import (
    "bufio"
    "fmt"
    "log"
    "os"
    "strings"
    "strconv"
)

func main() {
	var somme int
    file, err := os.Open("sample.csv")
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()

    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
		if !strings.Contains(scanner.Text(), "SERVER788") {
			continue
		}

		lineSplit := strings.Split(scanner.Text(), ",")

		s, err := strconv.Atoi(lineSplit[1])
		if err != nil {
			log.Println(err)
		}
		somme = somme + s 	
    }

	fmt.Println(somme)
    
    if err := scanner.Err(); err != nil {
        log.Fatal(err)
    }
}

Résultats

# awk (interprété)
$ /usr/bin/time awk -F, '/^SERVER788/{somme+=$2}END{print somme}' sample.csv 
12647755
Real	User	Sys	Cpu	MaxMem
0:00.15	0.15	0.00	98%	3764

# go (compilé)
$ /usr/bin/time ./parseSample2 
12647755
Real	User	Sys	Cpu	MaxMem
0:00.03	0.03	0.00	97%	6396

Edit:

Pour être tout à fait complet, j’ai également fait le test avec un code Python optimisé et avec mawk (awk super rapide utilisant un interpréteur bytecode, mais avec quelques limitations). Donc, en résumé:

awk     0.15 sec.  3764 kB
python  0.18 sec.  7160 kB
Go      0.03 sec.  6396 kB
mawk    0.04 sec.  1768 kB

On ne perd donc pas son temps à apprendre awk. Très utile pour le traitement de fichiers.

Bonjour,

Pour parser les fichiers/données JSON, il y a l’outil jq.