Découper un fichier texte selon un motif répétitif

Résolu/Fermé
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012 - 30 oct. 2012 à 08:55
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 - 7 nov. 2012 à 10:37
Bonjour,

Je dispose d'un fichier texte de grande taille (1,2 Go) qui représente plusieurs centaines de tables d'une base de données Postgresl. J'aimerais le découper en autant de fichiers textes, un par table.
Chaque "segment" commence par trois lignes de type remarque préfixées "--". Ensuite le mot clé "COPY" suivi d'un espace, le nom de la table (qu'on pourrait utiliser pour nommer les fichiers de tables), suivent les données séparées par des CR/LF et termine par "\."
Voici un extrait (2 lignes de données) :
--
-- Data for Name: a2_obje; Type: TABLE DATA; Schema: accidents; Owner: dig
--

COPY a2_obje (gemnr, objek, blatt, mang1, mang2, mang3, alkoh, anzpe, astaa, akate, fstaa, fkant, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, obj, but, col, prop, cond, perm, v36, v37, v38, per01, geb01, art01, sex01, sys01, fol01, tod01, per02, geb02, art02, sex02, sys02, fol02, tod02, per03, geb03, art03, sex03, sys03, fol03, tod03, per04, geb04, art04, sex04, sys04, fol04, tod04, katnr, permis, aseit) FROM stdin;
6621	1	1	170	423	0	0	1	CH 	C 	CH 	AG	215	244	262	270	280	286	000	000	000	000	000	215	244	\N	262	270	286	000	000	000	01	08051980	300	306	310	314	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	70022882	2002-03-28	28032002
6628	2	1	0	0	0	0	1	CH 	C 	CH 	GE	215	247	262	270	280	286	000	000	000	000	000	215	247	\N	262	270	286	000	000	000	01	30121961	300	306	310	314	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	100000614	1990-02-06	6021990 \.


Pour être tout à fait clair, il s'agit d'un dump (sauvegarde) effectué avec le paramètre COPY au lieu du paramètre SQL. Suite à la migration, je dois reconstruire les tables en SQL mais ne dispose que de ce fichier. Dans l'idéal, il s'agirait de transformer les choses ainsi :
COPY a2_obje en INSERT INTO a2_obje
FROM stdin; en VALUES
puis d'encadrer chaque ligne de données par des parenthèses et séparer les valeurs par des virgules...
Mais tout cela est bien au-delà de mes compétences... :-(

Merci par avance et meilleurs messages
Didier


A voir également:

9 réponses

dubcek Messages postés 18755 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 14 novembre 2024 5 621
30 oct. 2012 à 13:23
hello
essayer
$ awk '/^--/ || /^$/ {next} /^COPY/ {f=$2; next} {print > f}' fichier
$ cat a2_obje
6621	1	1	170	423	0	0	1	CH 	C 	CH 	AG	215	244	262	270	280	286	000	000	000	000	000	215	244	\N	262	270	286	000	000	000	01	08051980	300	306	310	314	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	70022882	2002-03-28	28032002
6628	2	1	0	0	0	0	1	CH 	C 	CH 	GE	215	247	262	270	280	286	000	000	000	000	000	215	247	\N	262	270	286	000	000	000	01	30121961	300	306	310	314	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	00	00000000	000	000	000	000	00000000	100000614	1990-02-06	6021990 \.
$ 
2
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
30 oct. 2012 à 16:12
Trooop Fooort ! C'est exactement la réponse à mon problème...
Merci beaucoup !!!
Je vais tenter des modifications en amont et m'inspirer de ce code pour générer les 221 tables à savoir :
- remplacer le COPY par INSERT INTO avec un sed;
- remplacer le FROM stdin; par VALUES (;
-remplacer le \. par un )
-remplacer les tabulations par des points-virgules.
Et hop, du coup je devrais avoir mes requêtes SQL prêtes pour réintroduire mes données !!!
Encore 1000 mercis à dubcek !
0
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 7 802
30 oct. 2012 à 08:59
J'ai beaucoup plus simple à te proposer. Pourquoi ne pas charger ces tables dans postgresql et ensuite dumper les tables une par une avec pg_dump, déjà ça réglerait le problème du découpage ?

Ensuite postgresql est tout à fait de charger un fichier csv.
https://stackoverflow.com/questions/2987433/how-to-import-csv-file-data-into-a-postgresql-table

Bonne chance
1
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
30 oct. 2012 à 09:38
Hello et merci pour ta réponse.
En fait, mon post était déjà assez long et je ne voulais pas surcharger. Le fichier en question provient déjà d'un pg_dump et ce sont des tables PostGIS (pas celle de l'exemple). En plus, il y a plusieurs centaines de tables... Je me vois mal passer un pg_dump pour chacune.
Et la raison de mon post est l'impossibilité de passer un pg_restore ! Il plante systématiquement
Merci encore pour l'intérêt.
0
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 7 802
Modifié par mamiemando le 30/10/2012 à 19:57
Dans l'absolu le nombre de table n'est pas un problème, car il est possible d'écrire une fonction en pgsql pour itérer sur chaque table. Tu peux par exemple écrire le fichier suivant (dump.sql) ou copier ce qui suit dans ton interpréteur pgsql :

CREATE OR REPLACE FUNCTION dump() RETURNS void AS $$ 
    DECLARE 
        v_filename        text; 
        v_query           text; 
        v_table_name      text; 
        v_latest_name     text; 
        v_master_id       integer; 
    BEGIN 
        FOR v_table_name IN 
            SELECT c.relname AS "Name" 
                FROM pg_catalog.pg_class c 
                    LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace 
                WHERE c.relkind = 'r' 
                    AND n.nspname NOT IN ('pg_catalog', 'pg_toast') 
                    AND pg_catalog.pg_table_is_visible(c.oid) 
                ORDER BY c.relname ASC 
        LOOP 
            v_filename = '/tmp/' || v_table_name || '.csv'; 
            v_query = 'COPY (SELECT * FROM ' || v_table_name || ') TO '  
                quote_literal(v_filename) ' WITH CSV HEADER '; 
            RAISE NOTICE 'Query: %', v_query; 
            EXECUTE v_query; 
        END LOOP; 
    END 
$$ LANGUAGE plpgsql;


Pour charger dump.sql :

psql -U postgres -d monschema < dump.sql


Ensuite, je ne comprends pas pourquoi utiliser pg_restore (et sans message d'erreur difficile de dire pourquoi il plante). Pour moi, tu peux charger ce fichier en lançant :

psql -U postgres -d monschema < monfichier.sql


Il suffit ensuite de lancer la fonction :

psql -U postgres -d monschema 
select dump();


Bonne chance
0
Re-Salut et Merci d'insister car je pense que tu as la connaissance qui devrait m'aider à me tirer d'affaire... je suis un peu désespéré...
Je prépare une réponse plus complète avec explications détaillées et messages d'erreur que je posterai demain matin.
Merci par avance pour ton aide
Didier
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
31 oct. 2012 à 09:45
@mamiemando,
Je reviens avec plus de détails.
Je suis géographe et j'utilise postgresql-postgis sur un serveur récupéré (non répliqué) mis à dispo par le service informatique de mon entreprise.
Nos informaticiens ont fait une migration dudit serveur sous Debian, postgres 8.3 vers 8.4 et postgis 1.3.3 vers ???. Tout à bien passé... faut le dire vite... sauf la remontée des données... Voilà pour le décorum !
J'avais préalablement fait une sauvegarde de la bdd depuis phppgadmin avec l'option COPY (j'aurais dû faire SQL). C'est le fichier dont je parle à l'origine de ce post, un dump.sql de 1.2 Go.
Nous avons suivi les procédures décrites par postgis, à savoir recréer une nouvelle base de donnée, lui adjoindre les fonctions spatiales etc.
C'est au moment de vouloir utiliser le fichier dump.sql avec psql que tout s'est gâté !
Nous avons rencontrés rapidement des erreurs : commande invalide \N...
En découpant le dump, j'ai pu supprimer la partie créant les fonctions spatiales et isoler la partie création des tables et vues : OK !
Il ne reste(rait) plus qu'à remonter les données... :-(
Le fichier dump.sql s'arrête inexorablement avec cette erreur au sujet des \N!
C'est pourquoi, je tente de recréer le fichier en SQL avec des INSERT INTO au lieu du COPY ... FROM stdin;
Voilà l'état de la chose !
0
dubcek Messages postés 18755 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 14 novembre 2024 5 621
31 oct. 2012 à 10:39
et comme ça
$ awk '/^--/ || !NF {next} /^COPY/ {f=$2; $0="INSERT INTO " f " VALUES (" } {sub("\\\\\.$", ")"); gsub("\t", ";");  print > f}' fichier
awk: warning: escape sequence '\.' treated as plain '.'
$ more a2_obje
INSERT INTO a2_obje VALUES (
6621;1;1;170;423;0;0;1;CH ;C ;CH ;AG;215;244;262;270;280;286;000;000;000;000;000;215;244;\N;262;270;286;000;000;000;01;08051980;300;306;310;314;00000000;00;0
0000000;000;000;000;000;00000000;00;00000000;000;000;000;000;00000000;00;00000000;000;000;000;000;00000000;70022882;2002-03-28;28032002
6628;2;1;0;0;0;0;1;CH ;C ;CH ;GE;215;247;262;270;280;286;000;000;000;000;000;215;247;\N;262;270;286;000;000;000;01;30121961;300;306;310;314;00000000;00;00000
000;000;000;000;000;00000000;00;00000000;000;000;000;000;00000000;00;00000000;000;000;000;000;00000000;100000614;1990-02-06;6021990 )
$ 
$ 
0
dubcek Messages postés 18755 Date d'inscription lundi 15 janvier 2007 Statut Contributeur Dernière intervention 14 novembre 2024 5 621
31 oct. 2012 à 15:02
il manque un ; après VALUE (
$ awk '/^--/ || !NF {next} /^COPY/ {f=$2; $0="INSERT INTO " f " VALUES (;" } {sub("\\\\\.$", ")"); gsub("\t", ";");  print > f}' fichier
0
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
31 oct. 2012 à 15:47
Je regarde ça au plus vite... En tout cas 1000 mercis pour vos soluces !
Amitiés
Didier
0
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 7 802
Modifié par mamiemando le 31/10/2012 à 20:59
J'avais préalablement fait une sauvegarde de la bdd depuis phppgadmin avec l'option COPY (j'aurais dû faire SQL). C'est le fichier dont je parle à l'origine de ce post, un dump.sql de 1.2 Go.

Je pense que ça ne change pas grand chose car phppgadmin va a priori lancer pg_dump en arrière boutique, donc le résultat aurait été le même.

Nous avons suivi les procédures décrites par postgis, à savoir recréer une nouvelle base de donnée, lui adjoindre les fonctions spatiales etc.
C'est au moment de vouloir utiliser le fichier dump.sql avec psql que tout s'est gâté !
Nous avons rencontrés rapidement des erreurs : commande invalide \N...


Encore une fois, as-tu simplement essayé de charger le dump original avec une commande du genre :

psql -U postgres -d monschema < monfichier.sql


As-tu essayé avec pg_restore (ou via phpphadmin) de restaurer ton dump ?

Le fichier dump.sql s'arrête inexorablement avec cette erreur au sujet des \N! C'est pourquoi, je tente de recréer le fichier en SQL avec des INSERT INTO au lieu du COPY ... FROM stdin;

Quel est le message d'erreur exact ? Car à mon avis tu n'es pas la première personne qui aurait pu rencontrer le problème.

Ensuite une question qu'on peut se poser c'est si tu as vraiment besoin d'héberger un serveur de carte chez toi) quand il existe des serveurs de carte publics comme google.maps (ou même des projets libres comme openstreetmap, mapserver)...

Bonne chance
0
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
Modifié par DiG360 le 31/10/2012 à 22:22
Hello,
Oui aux deux première questions (psql -U postgres... et pg_restore...)
Le message d'erreur est laconiquement : commande invalide \N et nous avons trouvé effectivement des questions à ce sujet sur le Net... malheureusement sans réponse utile pour nous !.

Pour ton dernier paragraphe??? J'utilise OSM et Mapserver pour créer des WMS avec les données contenues dans les tables POSTGIS. Je transforme parfois ces tables en GeoJson. Je n'utilise pas Gmaps car l'API est trop restrictif en matière de licences (mes cartes sont visibles uniquement en Intranet) qui oblige la visibilité depuis Internet et je privilégie OpenLayers...
Pour couronner le tout, je reçois du SITG (système d'information du territoire genevois http:/www.sitg.ch) de nombreuses couches de références vectorielles en shapes que je remonte de PostGis... Voilà voilà. De ce côté ça va.

1000 mercis pour ton aide et ton intérêt à mes questions.
Amitiés
Didier
0
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
31 oct. 2012 à 22:12
Encore une fois, as-tu simplement essayé de charger le dump original avec une commande du genre :

psql -U postgres -d monschema < monfichier.sql
0
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 7 802
1 nov. 2012 à 12:13
\N désigne la valeur NULL. Il me faudrait un extrait minimal du dump qui illustre le problème (dans l'idée, le CREATE TABLE de la table sur laquelle il y a l'erreur et le COPY ou le INSERT qui échoue).

Sans ça c'est difficile de comprendre d'où vient le problème.
0
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
2 nov. 2012 à 09:58
Hello,
C'est justement le paradoxe du message d'erreur qui dit que \N (NULL) est une commande invalide !
0
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 7 802
6 nov. 2012 à 19:35
J'attends toujours le dump :-)
0
DiG360 Messages postés 9 Date d'inscription mardi 30 octobre 2012 Statut Membre Dernière intervention 7 novembre 2012
7 nov. 2012 à 06:27
Oups ! Sorry !
En fait, il y avait un extrait (qui provoque l'erreur également) dans mon post d'origine ! ;-)
D'autre part, nous avons enfin pu reconstruire les tables les plus vitales grâce aux découpages de dubcek, que je remercie encore une fois au passage.
Et un grand MERCI à toi aussi mamiemando pour l'intérêt que tu as mobilisé pour m'aider et les indications que tu nous as données pour nous y retrouver.
Je vais clore ce post par un résolu.
0
mamiemando Messages postés 33372 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 22 novembre 2024 7 802
7 nov. 2012 à 10:37
Parfait :-) Bonne continuation
0