# Parsing d'un fichier

**URL:** <https://www.debian-fr.org/t/parsing-dun-fichier/74906>\
**Category:** Programmation\
**Created:** [Octobre 27, 2017, 4:30 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906 "2017-10-27T16:30:13Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![djbad](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/d/9fc348/32.png) [@djbad](https://www.debian-fr.org/u/djbad)\
**Post date:** [Octobre 27, 2017, 4:30 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/1 "2017-10-27T16:30:13Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![anon96191775](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/71c47a/32.png) [@anon96191775](https://www.debian-fr.org/u/anon96191775)\
**Post date:** [Octobre 28, 2017, 6:37 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/2 "2017-10-28T06:37:32Z")

</div>

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 :

```auto
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

```

---

<div class="post-metadata">

**Author:** ![Watael](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/w/a4c791/32.png) [@Watael](https://www.debian-fr.org/u/Watael)\
**Post date:** [Octobre 28, 2017, 7:41 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/3 "2017-10-28T07:41:05Z")

</div>

beurk.

```auto
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

```auto
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.*'

```

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Novembre 8, 2017, 6:41 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/4 "2017-11-08T06:41:25Z")

</div>

Si la structure des données ne change pas:

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

---

<div class="post-metadata">

**Author:** ![Watael](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/w/a4c791/32.png) [@Watael](https://www.debian-fr.org/u/Watael)\
**Post date:** [Novembre 8, 2017, 2:43 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/5 "2017-11-08T14:43:35Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Novembre 8, 2017, 4:18 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/6 "2017-11-08T16:18:24Z")

</div>

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
```

---

<div class="post-metadata">

**Author:** ![anon96191775](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/a/71c47a/32.png) [@anon96191775](https://www.debian-fr.org/u/anon96191775)\
**Post date:** [Novembre 16, 2017, 6:24 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/7 "2017-11-16T18:24:14Z")

</div>

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

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

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Novembre 18, 2017, 1:39 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/8 "2017-11-18T13:39:35Z")

</div>

Deux liens parmi de nombreux tuto:

> **[An intro to the great language with the strange name](https://www.ibm.com/developerworks/library/l-awk1/index.html)**
>
> Awk is a very nice language with a very strange name. In this first article of a three-part series, Daniel Robbins will quickly get your awk programming skills up to speed. As the series progresses, more advanced topics will be covered, culminating...

  
[https://www.gnu.org/software/gawk/manual/gawk.html](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.

---

<div class="post-metadata">

**Author:** ![ripat](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/r/bc79bd/32.png) [@ripat](https://www.debian-fr.org/u/ripat)\
**Post date:** [Novembre 18, 2017, 3:13 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/9 "2017-11-18T15:13:33Z")

</div>

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](https://gist.githubusercontent.com/owulveryck/4f9ddb952c5f1ef708b60a9907733969/raw/cbd3240f4b72ee259c294535c04523db09637e9e/Generation.sh) 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.

---

<div class="post-metadata">

**Author:** ![Totor](https://www.debian-fr.org/letter_avatar_proxy/v4/letter/t/58f4c7/32.png) [@Totor](https://www.debian-fr.org/u/Totor)\
**Post date:** [Décembre 8, 2017, 2:04 UTC](https://www.debian-fr.org/t/parsing-dun-fichier/74906/10 "2017-12-08T14:04:01Z")

</div>

Bonjour,

Pour parser les fichiers/données JSON, il y a l’outil [jq](https://stedolan.github.io/jq/).
