Supprimer des lignes vides à l'aide de sed

351

J'essaie de supprimer les lignes vides en utilisant sed:

sed '/^$/d'

mais je n'ai pas de chance avec ça.

Par exemple, j'ai ces lignes:

xxxxxx


yyyyyy


zzzzzz

et je veux que ce soit comme:

xxxxxx
yyyyyy
zzzzzz

Quel devrait être le code pour cela?

Jonas
la source
2
votre commande sed semble bien, cela devrait fonctionner
perreal
La commande ci-dessus ne fonctionnerait pas même si vous n'avez pas d'espace / tabulation mais des fins de ligne CR + LF .
devnull

Réponses:

628

Vous pouvez avoir des espaces ou des tabulations dans votre ligne "vide". Utilisez les classes POSIX avec sedpour supprimer toutes les lignes contenant uniquement des espaces:

sed '/^[[:space:]]*$/d'

Une version plus courte qui utilise ERE, par exemple avec gnu sed:

sed -r '/^\s*$/d'

(Notez que sed ne prend PAS en charge PCRE.)

Kent
la source
3
@HuStmpHrrr gnu sed ne prend pas du tout en charge PCRE. c'est ERE avec-r
Kent
8
OS X nécessaire sed -i "" '/^[[:space:]]*$/d' <filename>,
jww
@BernieReiter ^\s*$correspondra à toutes les lignes "vides", vide signifie ici, la ligne ne contient aucun caractère ou la ligne ne contient que des chaînes vides (par exemple des espaces). Toutes les lignes correspondantes seront supprimées par sed, avec la dcommande.
Kent
96

Je manque la awksolution:

awk 'NF' file

Qui reviendrait:

xxxxxx
yyyyyy
zzzzzz

Comment cela marche-t-il? Puisque NFsignifie "nombre de champs", ces lignes étant vides ont 0 fiedls, de sorte que awk évalue 0 à False et aucune ligne n'est imprimée; cependant, s'il y a au moins un champ, l'évaluation est True et fait awkeffectuer son action par défaut: imprimer la ligne courante.

fedorqui 'SO arrête de nuire'
la source
1
Whoah. Fonctionne même avec la version "minimisée" de awk de BSD (version 20121220 (FreeBSD). Merci :-)
Bernie Reiter
@BernieReiter vous êtes les bienvenus :) Oui, c'est une chose idiomatique très basique que toutes les versions awk autorisent.
fedorqui 'SO arrêtez de nuire'
Et c'est tellement plus rapide bien que - pour un test rapide et sale - j'invoque awk deux fois: $ time (topic companies <data.tpx | awk 'NF' - | awk -f dialog_menu.awk -) real 0m0.006s user 0m0.000s sys 0m0.008s $ time (topic companies <data.tpx | gsed '/^\s*$/d' | awk -f dialog_menu.awk -) real 0m0.014s user 0m0.002s sys 0m0.006s Connaissez-vous un moyen astucieux de l'inclure dans un script awk comme, par exemple, un modèle? awk '/ mypattern / {do stuff ...}'
Bernie Reiter
@BernieReiter vous pouvez dire awk 'NF {do stuff...}'.
fedorqui 'SO arrêtez de nuire'
1
Notez que cela ignorera également les lignes avec des espaces uniquement.
wisbucky
60

sed '/^$/d'devrait être bien, prévoyez-vous de modifier le fichier en place? Si c'est le cas, vous devez utiliser le -idrapeau.

Peut-être que ces lignes ne sont pas vides, donc si c'est le cas, regardez cette question Supprimer les lignes vides des fichiers txt, supprimer les espaces du début et de la fin de la ligne Je pense que c'est ce que vous essayez d'atteindre.

Alberto Zaccagni
la source
Oui. je modifie un fichier. * .csv. comment placer le -i dans la commande sed?
jonas
2
sed -i '/^$/d'est une façon de le faire.
Alberto Zaccagni
49

sed

grep

awk

Oleg Mazko
la source
1
Ceux-ci s'affichent correctement dans votre outil en ligne, mais ne[] doivent pas être échappés dans une expression entre crochets, donc le code ici n'est pas correct pour \[\[:space:\]\]ou \[ \t\]- devrait être [[:space:]]et [ \t].
Benjamin W.
1
@BenjaminW. Merci d'avoir attrapé ça. Ceux-ci n'étaient pas de l'auteur original, mais provenaient de Edit 3 quand il est passé du texte normal au "code", qui a ensuite "exposé" l'échappement `\ '. Je les ai réparés maintenant.
wisbucky
30

Je pense que c'est le plus simple et le plus rapide:

cat file.txt | grep .

Si vous devez également ignorer toutes les lignes d'espace blanc, essayez ceci:

cat file.txt | grep '\S'

Exemple:

s="\
\
a\
 b\
\
Below is TAB:\
    \
Below is space:\
 \
c\
\
"; echo "$s" | grep . | wc -l; echo "$s" | grep '\S' | wc -l

les sorties

7
5
Vadim
la source
5
Pas besoin de cat, grepprend également les fichiers:grep . file.txt
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
3
Oui, je sais, mais la question initiale ne mentionnait pas si la source était un fichier ou quelque chose d'autre, donc la solution est ce qui vient après "|", et avant cela juste un exemple de source. Simplement pour distinguer la solution de la source des lignes.
Vadim
2
grep '\S'n'est certainement pas portable. Si vous l'avez, grep -Pvous pouvez l'utiliser, grep -P '\S'mais ce n'est pas pris en charge sur toutes les plateformes non plus.
tripleee
L'inconvénient de grep .par rapport aux autres solutions est qu'il mettra en évidence tout le texte en rouge. Les autres solutions peuvent conserver les couleurs d'origine. Comparer unbuffer apt search foo | grep .avecunbuffer apt search foo | grep -v ^$
wisbucky
15

Avec l'aide de la réponse acceptée ici et de la réponse acceptée ci-dessus, j'ai utilisé:

$ sed 's/^ *//; s/ *$//; /^$/d; /^\s*$/d' file.txt > output.txt

`s/^ *//`  => left trim
`s/ *$//`  => right trim
`/^$/d`    => remove empty line
`/^\s*$/d` => delete lines which may contain white space

Cela couvre toutes les bases et fonctionne parfaitement pour mes besoins. Bravo aux affiches originales @Kent et @kev

Escroc
la source
5

Tu peux dire:

sed -n '/ / p' filename    #there is a space between '//'
réservoir
la source
.. ce qui signifie print all lines except the empty one(s)et tais
toi
3

Une autre option sans sed, awk, perl, etc.

strings $file > $output

strings - imprime les chaînes de caractères imprimables dans les fichiers.

user319660
la source
Voulez-vous dire stringsau lieu de string?
Mickael B.
Salut @MickaelB. Vous avez raison, je le répare.
user319660
2

Vous pouvez aussi faire quelque chose comme ça en utilisant "grep":

egrep -v "^$" file.txt
Lowbit
la source
2

Cela fonctionne également en awk.

awk '!/^$/' file
xxxxxx
yyyyyy
zzzzzz
Claes Wikner
la source
2

Vous voyez très probablement le comportement inattendu car votre fichier texte a été créé sur Windows, donc la séquence de fin de ligne est \r\n. Vous pouvez utiliser dos2unix pour le convertir en un fichier texte de style UNIX avant d'exécuter sed ou d'utiliser

sed -r "/^\r?$/d"

pour supprimer les lignes vides, que le retour chariot soit présent ou non.

FauChristian
la source
Salut, que fait le -rdrapeau et est-il possible de le combiner avec -ipour modifier le fichier directement et éviter d'imprimer à l'écran. De plus, je pense que cette commande fonctionnerait également commesed -r "/^\r$/d"
Alexander Cska
0

Ma bashréponse spécifique est de recommander l'utilisation d' perlun opérateur de substitution avec le modèle globalg indicateur de pour cela, comme suit:

$ perl -pe s'/^\n|^[\ ]*\n//g' $file
xxxxxx
yyyyyy
zzzzzz

Cette réponse illustre la prise en compte de la présence ou non d'espaces dans les lignes vides ([\ ]* ), ainsi que l'utilisation |pour séparer plusieurs termes / champs de recherche. Testé sur macOS High Sierra et CentOS 6/7.

Pour info, le code original de l'OP sed '/^$/d' $filefonctionne très bien dans bashTerminal sur macOS High Sierra et CentOS 6/7 Linux sur un cluster de superordinateurs hautes performances.

justincbagley
la source
-3

Pour moi, avec FreeBSD 10.1 avec sed n'a fonctionné que cette solution:

sed -e '/^[     ]*$/d' "testfile"

à l'intérieur []il y a des symboles d'espace et de tabulation.

le fichier de test contient:

fffffff next 1 tabline ffffffffffff

ffffffff next 1 Space line ffffffffffff

ffffffff empty 1 lines ffffffffffff

============ EOF =============
Vitaly
la source