Comment supprimer plusieurs lignes vierges d'un file?

J'ai quelques files de text que j'utilise pour prendre des notes dans – juste du text simple, habituellement juste en utilisant cat >> file. Parfois, j'utilise une ligne vide ou deux (juste return – le caractère de nouvelle ligne) pour spécifier un nouveau sujet / ligne de pensée. A la fin de chaque session – avant de fermer le file avec ctrl-D – j'ajoute typiquement des lignes vierges (5-10) vides (return-key) juste pour séparer les sessions.

Ce n'est évidemment pas très cleaver, mais cela fonctionne pour moi dans ce but. Je termine cependant avec beaucoup et beaucoup de lignes vierges inutiles, donc je cherche un moyen d'enlever (la plupart) des lignes supplémentaires. Existe-t-il une command Linux (couper, coller, grep, …?) Qui pourrait être utilisée directement avec quelques options? Sinon, est-ce que quelqu'un a une idée pour un script sed, awk ou perl (bien dans n'importe quel langage de script vraiment, bien que je préfère sed ou awk) qui ferait ce que je veux? Ecrire quelque chose en C ++ (que je pourrais faire moi-même), semble juste exagéré …

Cas n ° 1: Ce dont j'ai besoin est un script / command qui supprime plus de deux (3) lignes vides consécutives et les remplace par deux lignes vides. Bien que ce serait bien si elle pouvait aussi être modifiée pour supprimer plus d'une ligne (2 ou plus) et / ou replace plusieurs lignes vierges par une seule ligne vide.

Cas n ° 2: Je pourrais aussi utiliser un script / command qui supprimerait une seule ligne vierge entre deux lignes de text, mais laisserait plusieurs lignes vides telles quelles (même si la suppression d'une ligne vierge serait également acceptable).

PS: Oui, je devrais absolument apprendre des scripts avancés (?) Sed et awk, ainsi que perl … il est attendu depuis longtime. Mais comme je me suis promis de le faire après avoir lu un très bon livre Linux en 1995, je ne suis pas si optimiste que je le ferai.

Cas 1:

 awk '!NF {if (++n <= 2) print; next}; {n=0;print}' 

Cas 2:

 awk '!NF {s = s $0 "\n"; n++; next} {if (n>1) printf "%s", s; n=0; s=""; print} END {if (n>1) printf "%s", s}' 

Vous pouvez utiliser uniq pour uniq plusieurs occurrences de lignes vides en une seule ligne vide, mais il réduira également les lignes qui contiennent du text si elles sont identiques et inférieures les unes aux autres.

Cas 1:

 perl -i -ane '$n=(@F==0) ? $n+1 : 0; print if $n<=2' 

Cas 2:

 perl -i -ane '$n=(@F==0) ? $n+1 : 0; print $n==2 ? "\n$_" : $n==1 ? "" : $_ ' 

Vous pouvez adresser le cas # 1 comme ceci avec GNU sed:

 sed -r ':a; /^\s*$/ {N;ba}; s/( *\n *){2,}/\n\n/' 

C'est-à-dire, collecter des lignes vides dans l'espace des motifs, et s'il y a plus de trois lignes ou plus, réduisez-le à deux lignes.

Pour joindre des lignes à interligne simple, comme dans le cas n ° 2, vous pouvez le faire comme ceci:

 sed -r '/^ *\S/!b; N; /\n *$/!b; N; /\S *$/!b; s/\n *\n/\n/' 

Ou sous forme commentée:

 sed -r ' /^ *\S/!b # non-empty line N # /\n *$/!b # followed by empty line N # /\S *$/!b # non-empty line s/\n *\n/\n/ # remove the empty line ' 

Suite à la suggestion d' Anthon d'utiliser "uniq" …

Supprimez les lignes vides en début, fin et en double.

 # Get large random ssortingng. rand_str=; while [[ ${#rand_str} -lt 40 ]]; do rand_str=$rand_str$RANDOM; done # Add extra lines at beginning and end of stdin. (echo $rand_str; cat; echo $rand_str) | # Convert empty lines to random ssortingngs. sed "s/^$/$rand_str/" | # Remove duplicate lines. uniq | # Remove first and last line. sed '1d;$d' | # Convert random ssortingngs to empty lines. sed "s/$rand_str//" 

Dans une longue ligne:

 (rand_str=; while [[ ${#rand_str} -lt 40 ]]; do rand_str=$rand_str$RANDOM; done; (echo $rand_str; cat; echo $rand_str) | sed "s/^$/$rand_str/" | uniq | sed '1d;$d' | sed "s/$rand_str//") 

Ou utilisez simplement "chat -s".

Je suis passé des parenthèses aux accolades afin de restr dans le context actuel de la coquille que je suppose être plus efficace. Notez que les accolades nécessitent un point-virgule après la dernière command et nécessitent un espace pour la séparation.

 # Add extra blank lines at beginning and end. # These will be removed in final step. { echo; cat; echo; } | # Replace multiple blank lines with a single blank line. cat -s | # Remove first and last line. sed '1d;$d' 

En une seule ligne.

 { { echo; cat; echo; } | cat -s | sed '1d;$d'; } 

Cette solution prend également en count les dernières lignes vides dans le file:

 sed -r -n ' /^ *$/!{p;b} # non-blank line - print and next cycle h # blank line - save it in hold space :loop $b end # last line - go to end n # read next line in pattern space /^ *$/b loop # blank line - loop to next one :end # pattern space has non-blank line or last blank line /^ *$/{p;b} # last blank line: print and exit H;x;p # non-blank line: print hold + pattern space and next cycle '