Créer un fichier CSV à partir d'un fichier texte avec des jetons d'en-tête à l'aide de scripts shell
Je souhaite créer un fichier CSV à partir d'un ensemble de fichiers texte dans un répertoire avec la structure suivante pour les importer ultérieurement dans une base de données.
Title:
Article title
Word Count:
100
Summary:
Article summary.
Can consist of multiple lines.
Keywords:
keyword1, keyword2, keyword3
Article Body:
The rest of the article body.
Till the end of the file.
Le résultat souhaité est donc de les avoir dans un fichier CSV avec des sections comme en-têtes avec leur contenu comme suit.
Title | Word Count | Summary | Keywords | Article Body |
Article title | 100 | Article summary.\nCan... | keyword1, keyword2, keyword3 |... |
Article2 title | 110 | Article summary.\nCan... | keyword1, keyword2, keyword3 |... |
J'ai essayé quelques approches avec des scripts awk et shell, mais je n'ai pas réussi jusqu'à présent. Des idées?
Solution du problème
Selon la documentation de COPY, PostgreSQL prend entièrement en charge le format CSV, ainsi qu'un format TEXT qui est par défaut compatible avec le format TSV sans perte.
Parce que j'utilise awk
, je choisis de sortir un format TSV. La raison en est qu'il y a des nouvelles lignes dans les données et POSIX awk
ne permet pas de stocker des nouvelles lignes littérales dans une variable définie par l'utilisateur. Le format TSV n'a pas ce problème car vous remplacerez les retours à la ligne par \n
dans les données.
De plus, j'ai modifié le format d'entrée pour faciliter l'analyse. La règle est qu'une ou plusieurs lignes vides délimitent les blocs, ce qui signifie que vous ne pouvez plus avoir de lignes vides dans le contenu de Summary
ou Article Body
plus (j'ai ajouté un espace dans l'exemple).
Exemple d'entrée :
Title:
Article title
Word Count:
100
Summary:
Article summary.
Can consist of multiple lines.
Keywords:
keyword1, keyword2, keyword3
Article Body:
The rest of the article body.
Till the end of the file.
Et voici la awk
commande (qui est capable de traiter plusieurs fichiers en une seule fois) :
edit : les noms des champs dans l'en-tête sont maintenant convertis en cas de serpent
awk -v RS='' -v FS='^$' -v OFS='\t' '
FNR == 1 { fn++ }
/^[^:\n]+:/ {
fieldName = substr($0,1,index($0,":")-1)
sub("^[^:]+:[^\n]*\n","")
gsub(/\\/,"\\\\")
gsub(/\n/,"\\n")
gsub(/\r/,"\\r")
gsub(/\t/,"\\t")
header[fieldName]
record[fn,fieldName] = $0
}
END {
out = sep = ""
for (fieldName in header) {
gsub(/ /,"_",fieldName)
out = out sep tolower(fieldName)
sep = OFS
}
print out
for (i = 1; i <= fn; i++) {
out = sep = ""
for (fieldName in header) {
out = out sep record[fn,fieldName]
sep = OFS
}
print out
}
}
' *.txt
Le résultat:
summary article_body word_count title keywords
Article summary.\n \nCan consist of multiple lines. The rest of the article body.\n \nTill the end of the file. 100 Article title keyword1, keyword2, keyword3
PS: Une fois que vous avez un fichier TSV valide, vous pouvez utiliser un autre outil comme mlr
pour le convertir en CSV, JSON, etc... mais dans le but de l'importer dans postgreSQL, ce n'est pas obligatoire.
Voici la commande SQL (non testée) :
COPY tablename FROM '/path/file.tsv' HEADER;
note : Il semble que vous n'ayez pas besoin de spécifier le FORMAT
ni le DELIMITER
car les valeurs par défaut sont text
et\t
Commentaires
Enregistrer un commentaire