J'ai des enregistrements peu structurés dans un fichier constitué de 3 ou 4 lignes de texte séparées (le plus souvent) par une ligne vierge. Tous les enregistrements ne comportent pas de séparateur de ligne vide, mais la dernière ligne de chacun commence par le mot "Ajouté". Je voudrais produire un fichier csv avec chaque enregistrement sur une ligne précédée de son numéro de ligne. Jusqu'à présent, je n'ai pu produire qu'une concaténation de tous les enregistrements séparés par un nombre arbitraire d'espaces et une virgule redondante.
Logiquement, j'essaie d'atteindre les objectifs suivants:
Lire la ligne, si la ligne commence 'Ajoutée' conserver la nouvelle ligne à la fin
sinon remplacer 'newline' par ','
ou si la ligne est vide, supprimez-le
fin si
Échantillon de données:
Peter Green
Space Monkey at Area 51
Joined
Added by SF 3 weeks ago
Will Rossiter
Joined
Added by SF 3 weeks ago
Dean Matthews
Guitarist at Blues
Joined
Added by SF 3 weeks ago
Hobbit Mak
Farnborough, United Kingdom
Joined
Added by SF 3 weeks ago
Keneth W Moorfield
THE STOREMAN
Joined
Added by SF 3 weeks ago
Mick Georgious
Software Engineer
Joined
Added by SF 3 weeks ago
Essayer:
awk '/./{ printf "%s%s", $0, (/Added/?"\n":",") }' data
En utilisant vos exemples de données d'entrée:
$ awk '/./{printf "%s%s",$0,(/Added/?"\n":",")}' data
Peter Green,Space Monkey at Area 51,Joined,Added by SF 3 weeks ago
Will Rossiter,Joined,Added by SF 3 weeks ago
Dean Matthews,Guitarist at Blues,Joined,Added by SF 3 weeks ago
Hobbit Mak,Farnborough, United Kingdom,Joined,Added by SF 3 weeks ago
Keneth W Moorfield,THE STOREMAN,Joined,Added by SF 3 weeks ago
Mick Georgious,Software Engineer,Joined,Added by SF 3 weeks ago
Comment ça fonctionne:
/./{...}
Cela exécute les commandes entre accolades uniquement si la ligne contient un caractère. En d'autres termes, cela ignore les lignes vides.
printf "%s%s",$0,(/Added/?"\n":",")
Ceci affiche la ligne, notée $0
, suivie d’une virgule ou d’une nouvelle ligne selon que la ligne correspond à la regex Added
.
Voici une solution possible sed
(avec awk
, faites la numérotation des lignes):
$ sed -n -e :a -e '$!{/^$/!N}; /,Added/ {P;D}; s/\n/,/; ta' data | awk '{print NR","$0}'
1,Peter Green,Space Monkey at Area 51,Joined,Added by SF 3 weeks ago
2,Will Rossiter,Joined,Added by SF 3 weeks ago
3,Dean Matthews,Guitarist at Blues,Joined,Added by SF 3 weeks ago
4,Hobbit Mak,Farnborough, United Kingdom,Joined,Added by SF 3 weeks ago
5,Keneth W Moorfield,THE STOREMAN,Joined,Added by SF 3 weeks ago
6,Mick Georgious,Software Engineer,Joined,Added by SF 3 weeks ago
Fondamentalement, nous continuons simplement à ajouter des lignes d’entrée non vides et à remplacer leurs nouvelles lignes par des virgules, sauf que nous vérifions à chaque itération si nous avons un enregistrement complet et, si nous en avons, nous le cracherions i.e.
:a
$!
puis ajoutez des lignes non vides à l'espace-modèle {/^$/!N}
/,Added/
, imprimez-le P
et supprimez-le D
de l'espace de répétitions/,/\n/
et revenez à a
en cas de succèsFWIW, voici une option Perl
:
$ Perl -lne '
Push @rec, $_ unless /^$/; if (/^Added/) {print join ",", ++$n, @rec; undef @rec;}
' data
1,Peter Green,Space Monkey at Area 51,Joined,Added by SF 3 weeks ago
2,Will Rossiter,Joined,Added by SF 3 weeks ago
3,Dean Matthews,Guitarist at Blues,Joined,Added by SF 3 weeks ago
4,Hobbit Mak,Farnborough, United Kingdom,Joined,Added by SF 3 weeks ago
5,Keneth W Moorfield,THE STOREMAN,Joined,Added by SF 3 weeks ago
6,Mick Georgious,Software Engineer,Joined,Added by SF 3 weeks ago