93 liens privés
De la commande tordue:
$ curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' | jq -r '.data.features[].properties.nom' | tee >(wc -l 1>&2) | grep -iFc hair
3711
6217
Décomposons:
curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' | \
jq -r '.data.features[].properties.nom' | \
tee >(wc -l 1>&2) | \
grep -iFc hair ;
curl
-f, --fail
(HTTP) Fail silently (no output at all) on server errors.
-s, --silent
Silent or quiet mode. Don't show progress meter or error messages. Makes Curl mute. It will still output the data
you ask for, potentially even to the terminal/stdout unless you redirect it.
Use -S, --show-error in addition to this option to disable progress meter but still show error messages.
résultat: un énorme json d'une ligne en console
curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' > zobi
taille du fichier:
du -sh zobi
3,4M zobi
nombre de char:
wc -c zobi
3486798 zobi
jq
jq is like sed for JSON data - you can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.
https://jqlang.github.io/jq/
jq -r '.data.features[].properties.nom'
. > à la racine du json
data > tout premier objet sous la racine
features[] > toutes le contenu du tableau features
properties.nom > la valeur de la clé nom de l'objet properties
Une représentation visuelle sur un 2 objets Feature du fichier via https://jsononline.net/fr/json-checker
{
"data": {
"type": "FeatureCollection",
"name": "Coiffeurs Blagueurs",
"features": [
{
"type": "Feature",
"properties": {
"nom": "Tete En L'hair Coiffure",
"lat": 49.181161,
"lng": -0.3767,
"num": "50",
"voie": "RUE CAPONIERE",
"ville": "CAEN",
"codepostal": "14000",
"markerinnerhtml": "<p><b>Tete En L'hair Coiffure</b></p><p><a class='button' target='_blank' href='https://www.google.com/maps/?q=Tete+En+L%27hair+Coiffure 50+RUE+CAPONIERE+CAEN'>Voir la devanture via Google Maps</a></p>",
"liinnerhtml": "<b>Tete En L'hair Coiffure</b><span>, CAEN (14000)</span>",
"addresse": "50 RUE CAPONIERE CAEN"
},
"geometry": {
"type": "Point",
"coordinates": [
-0.3767,
49.181161
]
}
},
{
"type": "Feature",
"properties": {
"nom": "Imagina'tif",
"lat": "47.268834",
"lng": "5.010264",
"num": "11",
"voie": "RUE CHRISTIAN MARVILLET",
"ville": "PERRIGNY-LES-DIJON",
"codepostal": "21160",
"markerinnerhtml": "<p><b>Imagina'tif</b></p><p><a class='button' target='_blank' href='https://www.google.com/maps/?q=Imagina%27tif 11+RUE+CHRISTIAN+MARVILLET+PERRIGNY-LES-DIJON'>Voir la devanture via Google Maps</a></p>",
"liinnerhtml": "<b>Imagina'tif</b><span>, PERRIGNY-LES-DIJON (21160)</span>",
"addresse": "11 RUE CHRISTIAN MARVILLET PERRIGNY-LES-DIJON"
},
"geometry": {
"type": "Point",
"coordinates": [
"5.010264",
"47.268834"
]
}
}
]
}
}
curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' | \
jq -r '.data.features[].properties.nom' > zobi_json ;
résultat:
Tete En L'hair Coiffure
Imagina'tif
...
tee
tee - Lire depuis l'entrée standard et écrire sur la sortie standard et dans des fichiers
wc -l > nombre de lignes du résultat
Le coup tordu qui change tout:
si je comprends bien, tu passes par tee sauf que au lieu de rediriger vers un fichier tu rediriges vers un sous-shell ? par contre je ne comprends pas pourquoi tu envoies ça sur stderr 1>&2
parce que sinon le flux serait capturé par le grep suivant :)
curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' | \
jq -r '.data.features[].properties.nom' | \
tee >(wc -l 1>&2) ;
résultat:
...
Atmosph'hair
L'hair Zen
Planet'hair
6217
grep
-i, --ignore-case
Ignorer les distinctions de casse dans les motifs et les données d'entrée, pour que les correspondances incluent les
caractères qui ne diffèrent que par leur casse.
-F, --fixed-strings
Interpréter le MOTIF comme étant une chaîne figée, pas une expression rationnelle.
-c, --count
Ne pas afficher les résultats normaux. À la place, afficher un décompte des lignes correspondant au motif pour chaque
fichier. Avec l'option -v, --invert-match (voir ci-dessous), afficher le nombre de lignes ne contenant pas le motif.
grep -iFc hair
grep va recevoir la liste de nom en entrée et chercher nombre occurences de hair
le total de noms avec wc -l étant exclu par le tee
curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' | \
jq -r '.data.features[].properties.nom' | \
grep -iFc hair ;
résultat (nombre de noms avec hair)
3711
la commande originale:
curl -fsS 'https://static.data.gouv.fr/resources/coordonnees-des-enseignes-de-coiffure-comportant-des-jeux-de-mots-cocasses-dans-leur-appellation/20231011-084948/coiffeurs.json' | \
jq -r '.data.features[].properties.nom' | \
tee >(wc -l 1>&2) | \
grep -iFc hair ;
6217
3711
C'est inversé par rapport au post d'origine, au prochain épisode...
"Alors ça c'est très tordu mais bougrement intelligent" ©Dîner de cons 1998