J'essaie d'extraire des informations d'un fichier JSON et d'écrire une partie du contenu dans un fichier CSV.
Voici un exemple de mon texte
"data":{"headers":{"sender":"[email protected]"
"to":"[email protected]"
"subject":"Help with this project"
"x-received-time":"14144273245408"
"received":"from abc.com ()\r\n by mail.mail.com with SMTP (Postfix)\r\n for [email protected];\r\n Mon
"from":"\"Help with this project\" <[email protected]>"
"date":"Mon, 27 Oct 2014 09:03:14 -0500"
"id":"1414427328-2345855-frank"
"to":"[email protected]"
"time":14144273245408
"subject":"Help with this project"
"fromfull":"[email protected]"
Je veux récupérer le contenu de: to, fromfull, id, subject, date et l'écrire dans un fichier csv où To correspond à la colonne A, fromfull à la colonne B, etc.
Quelqu'un peut-il offrir une assistance? Ceci est une réponse JSON.
Vous pouvez utiliser la commande Perl suivante pour créer la sortie CSV, ouvrir un terminal et taper:
Perl -n0e '@a= $_ =~ /"date":(".*?").*?"id":(".*?").*?"to":"(.*?)".*?".*?"subject":(".*?").*?"fromfull":"(.*?)"/gs; while (my @next_n = splice @a, 0, 5) { print join(q{,}, @next_n)."\n"}' inputfile.txt
Cela fonctionnera même si vous avez plusieurs en-têtes dans votre fichier d'entrée.
Notez que seul le dernier champ "à": est pris en compte (il semble que vos en-têtes fournissent les informations deux fois)
Le résultat de la commande:
"Mon, 27 Oct 2014 09:03:14 -0500","1414427328-2345855-frank",[email protected],"Help with this project",[email protected]
Vous pouvez convertir ce fichier JSON en fichier CSV sur une seule ligne avec jq
.
jq '.data.headers | [.sender, .to, .subject, ."x-received-time",
.received, .from, .date, .id, .to, .subject, .fromfull]
+ [(.time | tostring)] | join(", ")'
Panne:
.data.headers
- Emet des en-têtes en tant qu'objet .data[].headers
[…string keys list…]
- Émettre des valeurs de chaîne sous forme de tableau+ [(.time | tostring)]
- Emet du temps sous forme de chaîne et ajoute au tableaujoin(", ")
- Joignez les valeurs du tableau en utilisant une virgule et un espace Puisque vous travaillez avec des fichiers JSON, pourquoi ne pas l’analyser comme tel? Installez nodejs-legacy
et créez un script NodeJS tel que:
#!/usr/bin/env node
// parseline.js process lines one by one
'use strict';
var readline = require('readline');
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
terminal: false
});
rl.on('line', function(line){
var obj = JSON.parse(line);
// add the fields which you want to extract here:
var fields = [
obj.data.headers.to,
obj.data.headers.subject,
// etc.
];
// print the fields, joined by a comma (CSV, duh.)
// No escaping is done, so if the subject contains ',',
// then you need additional post-processing.
console.log(fields.join(','));
});
En supposant que vous ayez une chaîne JSON valide sur chaque ligne d'un fichier:
node parseline.js < some.txt
Ou si vous voulez vraiment lire un seul fichier et analyser les champs de celui-ci:
#!/usr/bin/env node
// parsefile.js - fully read file and parse some data out of it
'use strict';
var filename = process.argv[1]; // first argument
var fs = require('fs');
var text = fs.readFileSync(filename).toString();
var obj = JSON.parse(text);
// add the fields which you want to extract here:
var fields = [
obj.data.headers.to,
obj.data.headers.subject,
// etc.
];
// print the fields, joined by a comma (CSV, duh.)
// No escaping is done, so if the subject contains ',',
// then you need additional post-processing.
console.log(fields.join(','));
Puis lancez-le avec:
node parsefile.js yourfile.json > yourfile.csv
Vous pouvez utiliser jsonv de GitHub
Et ensuite la commande suivante:
cat YOUR_JSON_FILEname | jsonv to,fromfull,id,subject,date > output.csv
Voici une awk implémentation:
awk -F ":" '{gsub("\"","",$1);key=$1;sub(key " ","");gsub("\\","",$0);value[key]=$0; if ("fromfull"== key) print value["from"] ";" value["to"] ";" value["fromfull"] ";" value["id"] ";" value["subject"] ";" value["date"] ;}' jsonFile > csvFile
Ce script lit la ligne jusqu'à ce qu'elle trouve la ligne "fromfull", puis affiche la ligne csv
name__, de sorte qu'elle devrait également fonctionner avec plusieurs séquences.
Voici le résultat:
""Help with this project" <[email protected]>";"[email protected]";"[email protected]";"1414427328-2345855-frank";"Help with this project";"Mon, 27 Oct 2014 09 03 14 -0500"
Voici un script gawk que je viens de fouetter pour vous!
#!/usr/bin/gawk -f
BEGIN {
FS="\""
output=""
nodata=1
}
/^"data"/{
if( ! nodata )
{
gsub("|$","",output)
print output
nodata=0
}
output=""
}
/^"[^d][^a][^t][^a]/{
if ( $2 == "to" || $2 == "fromfull" || $2 == "id" || $2 == "subject" || $2 == "date" )
output=output$4"|"
}
END{
gsub("|$","",output)
print output
}
Cela devrait fonctionner sur un fichier avec un tas d'entrées similaires. Si vous souhaitez ajouter d'autres éléments à la liste, ajoutez-les simplement dans l'instruction if. J'ai cependant trouvé un problème avec votre ensemble de données: les dates. Ils contiennent des virgules, donc ce ne peut pas être un vrai CSV. Au lieu de cela, je l'ai juste séparé avec un autre personnage.