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=""
RS
Le premier caractère de la valeur de chaîne deRS
doit être le séparateur d'enregistrement d'entrée; apar défaut. Si RS
contient plus d'un caractère, les résultats ne sont pas spécifiés. SiRS
estnul
, 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