Je dois supprimer toutes les lignes vides d'un fichier d'entrée et l'écrire dans un fichier de sortie. Voici mes données ci-dessous.
11216,33,1032747,64310,1,0,0,1.878,0,0,0,1,1,1.087,5,1,1,18-JAN-13,000603221321
11216,33,1033196,31300,1,0,0,1.5391,0,0,0,1,1,1.054,5,1,1,18-JAN-13,059762153003
11216,33,1033246,31300,1,0,0,1.5391,0,0,0,1,1,1.054,5,1,1,18-JAN-13,000603211032
11216,33,1033280,31118,1,0,0,1.5513,0,0,0,1,1,1.115,5,1,1,18-JAN-13,055111034001
11216,33,1033287,31118,1,0,0,1.5513,0,0,0,1,1,1.115,5,1,1,18-JAN-13,000378689701
11216,33,1033358,31118,1,0,0,1.5513,0,0,0,1,1,1.115,5,1,1,18-JAN-13,000093737301
11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802041926
11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802041954
11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802049326
11216,33,1035476,37340,1,0,0,1.7046,0,0,0,1,1,1.123,5,1,1,18-JAN-13,045802049383
11216,33,1036985,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000093415580
11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781202001
11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781261305
11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781603955
11216,33,1037003,15151,1,0,0,1.4436,0,0,0,1,1,1.065,5,1,1,18-JAN-13,000781615746
sed -i '/^$/d' foo
Ceci dit à sed
de supprimer toutes les lignes correspondant à la regex ^$
_ c'est-à-dire chaque ligne vide. Le -i
flag édite le fichier sur place, si votre sed
ne prend pas en charge le fait que vous pouvez écrire le résultat dans un fichier temporaire et remplacer le fichier d'origine:
sed '/^$/d' foo > foo.tmp
mv foo.tmp foo
Si vous souhaitez également supprimer les lignes composées uniquement d'espaces (et pas seulement de lignes vides), utilisez:
sed -i '/^[[:space:]]*$/d' foo
Edit: supprime également les espaces à la fin des lignes, car apparemment vous en avez décidé vous aussi:
sed -i '/^[[:space:]]*$/d;s/[[:space:]]*$//' foo
awk 'NF' filename
awk 'NF > 0' filename
sed -i '/^$/d' filename
awk '!/^$/' filename
awk '/./' filename
La NF supprime également les lignes ne contenant que des blancs ou des tabulations, la regex /^$/
ne fait pas.
Utilisez grep pour faire correspondre toute ligne n’ayant rien entre l’ancre de départ (^
) et l'ancre d'extrémité ($
):
grep -v '^$' infile.txt > outfile.txt
Si vous souhaitez supprimer des lignes ne contenant que des espaces, vous pouvez toujours utiliser grep. J'utilise des expressions régulières Perl dans cet exemple, mais voici d'autres méthodes:
grep -P -v '^\s*$' infile.txt > outfile.txt
ou, sans expressions régulières Perl:
grep -v '^[[:space:]]*$' infile.txt > outfile.txt
sed -e '/^ *$/d' input > output
Supprime toutes les lignes composées uniquement de blancs (ou est complètement vide). Vous pouvez changer le blanc en [ \t]
où le \t
est une représentation de tab. Que votre shell ou votre sed
fasse l'expansion, mais vous pouvez probablement taper directement le caractère de tabulation. Et si vous utilisez GNU ou BSD sed
, vous pouvez effectuer la modification sur place, si c'est ce que vous voulez, avec le -i
option.
Si j'exécute la commande ci-dessus, j'ai toujours des lignes vides dans mon fichier de sortie. Quelle pourrait être la raison?
Il pourrait y avoir plusieurs raisons. Il se peut que vous n'ayez pas de lignes vierges, mais que vous ayez beaucoup d'espaces à la fin d'une ligne. Il semble donc que vous ayez des lignes vides lorsque vous affichez le fichier à l'écran. Si c'est le problème, alors:
sed -e 's/ *$//' -e '/^ *$/d' input > output
La nouvelle expression rationnelle supprime les espaces répétés à la fin de la ligne; voir la discussion précédente pour les blancs ou les onglets.
Une autre possibilité est que votre fichier de données provient de Windows et comporte des fins de ligne CRLF. Unix voit le retour de chariot à la fin de la ligne; ce n'est pas un blanc, donc la ligne n'est pas supprimée. Il y a plusieurs façons de gérer cela. Une solution fiable est tr
à supprimer (-d
) code de caractère octal 15, alias control-M ou \r
ou retour chariot:
tr -d '\015' < input | sed -e 's/ *$//' -e '/^ *$/d' > output
Si aucune de ces méthodes ne fonctionne, vous devez afficher un vidage hexadécimal ou octal (od -c
) des deux premières lignes du fichier, nous pouvons voir à quoi nous sommes confrontés:
head -n 2 input | od -c
A en juger par les commentaires que sed -i
ne fonctionne pas pour vous, vous ne travaillez pas sous Linux, Mac OS X ou BSD - sur quelle plate-forme travaillez-vous? (AIX, Solaris et HP-UX me viennent à l’esprit comme des possibilités relativement plausibles, mais il en existe de nombreuses autres moins plausibles.)
Vous pouvez essayer les classes de caractères nommés POSIX telles que sed -e '/^[[:space:]]*$/d'
; cela fonctionnera probablement, mais ce n'est pas garanti. Vous pouvez l'essayer avec:
echo "Hello World" | sed 's/[[:space:]][[:space:]]*/ /'
Si cela fonctionne, il y aura trois espaces entre le "Bonjour" et le "Monde". Sinon, vous obtiendrez probablement une erreur de sed
. Cela vous évitera peut-être de devoir taper des onglets sur la ligne de commande.
grep . file
grep regarde votre fichier ligne par ligne; le point .
correspond à tout sauf un caractère de nouvelle ligne. La sortie de grep correspond donc à toutes les lignes qui consistent en autre chose qu’une seule nouvelle ligne.
avec awk
awk 'NF > 0' filename
Vous pouvez sed's -i
option pour éditer sur place sans utiliser de fichier temporaire:
sed -i '/^$/d' file
Pour être complet et supprimer les lignes paires si elles incluent des espaces ou des tabulations, quelque chose comme ça en Perl le fera:
cat file.txt | Perl -lane "print if /\S/"
Bien sûr, il existe les équivalents awk et sed. Mieux vaut ne pas supposer que les lignes sont totalement vierges comme ^$
ferait.
À votre santé