J'essaie de fusionner plusieurs lignes en une seule mais avec des conditions supplémentaires.
Mon fichier d'entrée ressemble à:
awk '{printf("%s",$0)}'
Il y a donc plusieurs lignes qui sont également séparés par des lignes vides. Tous les * trucs * contiennent des expressions longues et compliquées qui peuvent également contenir des parenthèses.
Le résultat attendu est
Dm1*( stuff1 + stuff2 - stuff3 + stuff4) + D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 ) + D2*(D2stuff)
Toutes les tentatives actuelles comme
Dm1*( stuff1 + stuff2 - stuff3 + stuff4) + D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 ) + D2*(D2stuff)
mettent tout sur une seule ligne. Dois-je faire une boucle sur des lignes ou y a-t-il un moyen d'identifier les blocs entre les lignes vides et d'y appliquer quelque chose?
6 Réponses :
Essayez :
$ awk -v RS= '{gsub(/ *\n */, " "); print $0 ORS}' file
Dm1*( stuff1 + stuff2 - stuff3 + stuff4)
+ D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 )
+ D2*(D2stuff)
Comment ça marche:
-v RS =
Cela indique à awk d'utiliser des lignes vides comme séparateurs d'enregistrements.
gsub (/ * \ n * /, "")
Ceci dit à awk de remplacer toutes les nouvelles lignes dans l'enregistrement, ainsi que tous les espaces environnants, par un seul espace.
imprimer $ 0 ORS
Cela indique à awk d'imprimer l'enregistrement suivi d'un séparateur d'enregistrement de sortie, ORS , qui, par défaut, est une nouvelle ligne.
En plus de la très belle commande awk introduite par John1024 , vous pouvez également utiliser une approche sed pour votre problème.
Entrée:
Dm1*( stuff1 + stuff2 -stuff3 + stuff4) + D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 ) + D2*(D2stuff)
Commande:
sed -n '/^$/!{H};/^$/{x;s/\n//g;s/$/\n/;p;};${x;s/\n//g;p}' input_file
$ cat input_file Dm1*( stuff1 + stuff2 - stuff3 + stuff4) + D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 ) + D2*(D2stuff)
Explications: p>
-n désactiver l'impression automatique sed / ^ $ /! {H}; Lorsque sed rencontre une ligne non vide / ^ $ /! ajoutez cette ligne à la conserver l'espace via H / ^ $ / {x; s / \ n // g; s / $ / \ n /; p;} lorsque sed rencontre une ligne vide / ^ $ / , échangez l'espace de maintien et l'espace de motif x , supprimez tous les \ n dans la chaîne qui a été construite s / \ n // g , ajoutez un \ n à la fin de la chaîne s / $ / \ n / , imprimez-le p . $ {x; s / \ n // g; p} lorsque sed atteint la dernière ligne, effectuez l'échange d'espaces hold / pattern x , puis supprimez tous les \ n via s / \ n // g avant de l'imprimer p . awk '{if(NF!=0){printf $0}else{printf "\n\n"}}'
Encore un peu plus courte que la version de John1024
awk -v RS="" -v ORS="\n\n" '{$1=$1}1'
ou
awk 'BEGIN { RS=""; ORS="\n\n"}{$1=$1}1'
Utilisation de RS = "" code > dit à awk d'utiliser n'importe quel paragraphe comme enregistrement (c'est-à-dire un bloc de texte séparé par des lignes vides). Mais cela indique aussi à awk qu'un FS . En redéfinissant simplement le séparateur d'enregistrement de sortie ORS , nous pouvons tout afficher comme vous le souhaitez en disant à awk de redéfinir son enregistrement $ 0 en réinitialisant le premier enregistrement $ 1 = $ 1 . Cela a pour effet que tous les séparateurs de champ définis par FS (la valeur par défaut ici) et les nouvelles lignes (dues à RS = "" ) sont remplacés par OFS (par défaut un 1
Vous pouvez vous débarrasser de tous les espaces en définissant en plus OFS=""
RSLe premier caractère de la valeur de chaîne deRSdoit être le séparateur d'enregistrement d'entrée; apar défaut. Si RScontient plus d'un caractère, les résultats ne sont pas spécifiés. SiRSestnul, alors les enregistrements sont séparés par des séquences constituées d'uneplus une ou plusieurs lignes vides, les lignes vierges de début ou de fin ne doivent pas donner lieu à des enregistrements vides à le début ou la fin de l'entrée, et un sera toujours un séparateur de champ, quelle que soit la valeur de FS.source: POSIX awk standard
il manque un ' dans la seconde avant {?
Oui, c'est la bonne façon / idiomatique de faire cela avec awk.
Utilisation du mode paragraphe Perl
$ cat bogey.txt Dm1*( stuff1 + stuff2 - stuff3 + stuff4) + D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 ) + D2*(D2stuff) $ perl -00 -ne ' s/\n//g; print "$_\n\n" ' bogey.txt Dm1*( stuff1 + stuff2 -stuff3 + stuff4) + D1*(D1stuff1 + D1sstuff2 + D1stuff3 + D1stuff4 + D1stuff5 - D1stuff6 ) + D2*(D2stuff) $
avec vos entrées
perl -00 -ne ' s/\n//g; print "$_\n\n" ' file
Cela pourrait fonctionner pour vous (GNU sed):
sed ':a;N;/\n$/!s/\n//;ta' file
Rassemblez les lignes dans l'espace du motif, en supprimant les nouvelles lignes, jusqu'à ce qu'une ligne vide.
cela fonctionne pour GNU sed. Cependant, je préfère quelque chose qui fonctionne à la fois sur les plates-formes GNU et BSD car j'utilise souvent les deux.
@Boogeyman Peut-être que sed $ ': a; N; / \\ n $ /! S / \\ n //; ta' file fonctionnera ou peut-être sed -e ': a' -e $ 'N; / \\ n $ /! \\ n //; ta' fichier