J'ai un fichier .csv (sur un mac) qui a un tas de lignes vides, par exemple:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum
lorem ipsum ","2","3","4"
Que je veux convertir:
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
"1", "2", "lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum lorem ipsum ","2","3","4"
Je sais qu'il doit y avoir un paquebot mais je ne connais pas awk ou sed. Tous les conseils sont grandement appréciés!
shell
text-processing
sed
awk
pitosalas
la source
la source
Réponses:
Vous pouvez utiliser le mode grep
-v
(invert match) pour ce faire:Notez que ces fichiers doivent être différents, en raison du fonctionnement des redirections shell. Le fichier de sortie est ouvert (et vidé) avant la lecture du fichier d'entrée. Si vous avez des moreutils (pas par défaut sur Mac OS X), vous pouvez utiliser
sponge
pour contourner cela:Mais bien sûr, vous aurez plus de mal à revenir en arrière en cas de problème.
Si vos "lignes vierges" peuvent réellement contenir des espaces (cela semble être le cas), vous pouvez utiliser ceci à la place:
Cela ignorera les lignes vides ainsi que les lignes contenant uniquement des espaces. Vous pouvez bien sûr faire la même
sponge
transformation dessus.la source
egrep -v '^[[:space:]]*$'
... noter grep -> egrep et le nouveau motif étrangeiconv -f utf16le file.csv | head
ouiconv -f utf16be file.csv | head
L'option la plus simple est juste
grep .
. Ici, le point signifie "correspondre à n'importe quoi", donc si la ligne est vide, elle ne correspond pas. Sinon, il imprime la ligne entière telle quelle.la source
Pour supprimer les lignes vides, en place , avec ksh93:
L'
<>;
opérateur de redirection est spécifique à ksh93 et est le même que l'<>
opérateur standard , sauf que ksh tronque le fichier une fois la commande terminée.sed '/./!d'
est une façon compliquée d'écriregrep .
, mais malheureusement GNU grep se plaint au moins si sa sortie stdout pointe vers le même fichier que son stdin. Vous diriez que l'on pourrait écrire:Mais malheureusement, il y a un bogue dans ksh93 (au moins ma version (93u +)), en ce que le fichier semble être tronqué à zéro dans ce cas.
Semble contourner ce bogue, mais maintenant, il est beaucoup plus compliqué que la commande sed.
la source
awk '/./' file 1<>; file
ce qui a fonctionné. Pour moi, c'est encore plus clair quesed '/./!d'
Voici une
Perl
doublure pour cela:EDIT: Code amélioré basé sur les commentaires de ruakh ci-dessous.
la source
perl -ni -e '/./ and print' yourfile
$
est une ancre (c'est-à-dire de largeur nulle) donc elle exclut la nouvelle ligne. En ce qui concerne l'espace superflu, c'est la raison pour laquelle j'ai ajouté que/x
je ne voulaisPerl
pas essayer d'interpoler `$ \` dans l'expression régulière$
, étant donné que vous en avez\n
. (Alternativement - vous n'avez pas besoin du\n
, étant donné que vous avez le\s*
et le$
; mais je penses/^\s*\n//
qu'il est plus clair que la nouvelle ligne est supprimée.) Vous n'avez pas non plus besoin du/m
; cela n'a aucun effet sur cette commande. Et une fois que vous vous serez débarrassé de l'$
espace et de l'espace, vous n'en aurez plus besoin/x
.\n
lui - même peut être supprimé; ce que vous ne pouvez pas faire, c'est supprimer à la fois le$
et le\n
. Il ys/^\s*//
aurait donc le problème que vous décrivez, mais ces/^\s*$//
serait bien, à cause du\s*
et du$
. (Voyez-vous ce que je veux dire?)$
peut être effectuée avant une nouvelle ligne (à condition que l'/m
indicateur soit activé ou que la nouvelle ligne soit le tout dernier caractère de la chaîne, ou les deux), mais elle peut également correspondre à la fin de la chaîne. Par exemple,"abc" =~ m/^abc$/
c'est vrai. Dans le cas de\s*$
, le\s*
est suffisamment gourmand pour manger la nouvelle ligne, puis le$
correspond à la fin de chaîne. (Mais je pense ques/^\s*\n//
c'est plus clair, de toute façon, donc votre réponse est très bien comme elle est maintenant.)Sur la base de la clarification dans les commentaires de votre question, quelque chose comme:
peut faire ce que vous voulez.
Un séparateur d'enregistrements vide est un cas spécial qui indique
awk
que les enregistrements doivent être des paragraphes (séparés par des séquences de lignes vides). La définition du séparateur d'enregistrements de sortie sur la chaîne vide signifie également que le contenu de ces paragraphes (sans les séparateurs) doit être concaténé.1
est juste une vraie condition pour imprimer chaque enregistrement.Cela omettrait cependant la nouvelle ligne de fin, vous pouvez donc faire:
la source
Je sais que cela aurait été plus facile si j'avais donné le fichier, mais malheureusement, il contenait des informations confidentielles que je ne pouvais pas partager. En attendant je me suis écrit un script rubis qui semblait faire l'affaire:
Merci à tous pour votre aide!
la source
produit
la source
J'ai trouvé une idée pour une solution possible sur stackoverflow .
sed -i ':a;N;$!ba;s/[^"]\n\s*\n/ /g' file.csv
Vous devriez probablement sauvegarder votre fichier csv avant de le tester, mais au moins pour l'exemple que vous avez fourni, il fonctionne parfaitement.
Une bonne explication sur le fonctionnement interne de cette expression est offerte dans la réponse, je viens de la modifier pour rechercher des lignes qui ne se terminent pas par un
"
([^"]\n
).la source
Si, à partir de votre propre réponse, vous souhaitez supprimer les caractères de nouvelle ligne contenus dans les chaînes entre guillemets, vous pouvez faire:
Vous pouvez également utiliser l'
-i
indicateur perl pour modifier les fichiers en place .Ou avec GNU awk:
ou:
(si vous êtes en compétition pour le plus court)
Notez que les supposer qu'il n'y a pas échappèrent caractères à double citation dans l'entrée.
la source
Il semble en effet que vous souhaitiez plus que la suppression de lignes vides, mais supprimez chaque séquence de 2 ou plusieurs caractères de nouvelle ligne.
Ce que vous pourriez faire avec perl:
Vous pouvez également utiliser l'
-i
indicateur perl pour modifier les fichiers en place .la source
Il existe un moyen toujours plus court de supprimer les lignes vides dans
AWK
:awk 'NF' file
Mais pour obtenir la sortie que vous voulez, tout ce dont vous avez besoin est une simple doublure:
awk 'NF {printf("%s ", $0); i++;} !(i % 2) {printf("\n");}' file
Explication
Dans
AWK
, une ligne vide signifie que la ligne / l'enregistrement n'a pas de champs, c'est-à-dire que laNF
variable (Nombre de champs) est nulle. Le liner ci-dessus ne s'exécutera que lors de l'NF > 0
impression de toutes les lignes, mais les lignes vides.Le
i++
est le compteur de lignes non vide.Le
!(i % 2)
est utilisé pour imprimer deux lignes consécutives non vides à la manière de la sortie souhaitée, c'est-à-dire que chaque fois qu'un multiple de 2 est trouvé, l'modulo
instruction!(i % 2)
donne 1, ce qui termine la concaténation de deux lignes non vides.la source
Vous pouvez utiliser Vim en mode Ex:
v/./
trouver des lignes videsd
supprimerx
sauver et fermerla source