1314 votes

sed: Comment puis-je remplacer un saut de ligne (\n)?

Je unsuccesfully essayé:

sed 's#\n# #g' file
sed 's#^$# #g' file

Comment résoudre ce problème?

1653voto

dmckee Points 50318

Utiliser tr à la place?

tr '\n' ' ' < input_filename

1453voto

Zsolt Botykai Points 20615

Ou de l'utilisation de cette solution avec sed:

sed ':a;N;$!ba;s/\n/ /g'

Cela permettra de lire tout le fichier dans une boucle, puis remplace le saut de ligne(s) avec un espace.

Mise à jour: explication.

  1. créer un label via :a
  2. ajouter le courant et la ligne suivante à la structure de l'espace par N
  3. si nous sommes avant la dernière ligne, de la direction générale de l'étiquette créée $!ba ($! moyen de ne pas le faire sur la dernière ligne (comme il se doit un dernier saut de ligne)).
  4. enfin, la substitution remplace chaque retour à la ligne avec un espace sur le modèle de l'espace (qui est l'ensemble du fichier).

468voto

hdorio Points 3332

Réponse rapide:

sed ':a;N;$!ba;s/\n/ /g' file
  1. : créer un label "a"
  2. N ajouter la ligne suivante à la structure de l'espace
  3. $! si ce n'est la dernière ligne, ba branche (aller à) l'étiquette "a"
  4. s remplacer, /\n/ regex pour la nouvelle ligne, / / par un espace, /g global de match (autant de fois qu'il le peut)

sed en boucle à travers les étapes 1 à 3 jusqu'à atteindre la dernière ligne, l'obtention de toutes les lignes d'ajustement dans le modèle de l'espace où sed remplace tous les caractères \n


Alternatives:

Toutes les solutions de rechange, à la différence de la sed n'aurez pas besoin d'atteindre la dernière ligne pour commencer le processus

avec bash, lent

while read line; do printf "%s" "$line "; done < file

avec perl, sedcomme la vitesse

perl -p -e 's/\n/ /' file

avec tr, plus rapide que le sed, peut les remplacer par un seul caractère

tr '\n' ' ' < file

avec la pâte, tr-comme la vitesse, peut les remplacer par un seul caractère

paste -s -d ' ' file

avec awk, trde la vitesse

awk 1 ORS=' ' file

D'autres alternatives comme "echo $(< fichier)" est lente, ne fonctionne que sur les petits fichiers et des besoins pour traiter l'intégralité du fichier pour lancer le processus.


Réponse longue à partir de la sed FAQ 5.10:

5.10. Pourquoi ne puis-je pas de match ou de supprimer un saut de ligne à l'aide de l' \n échapper
séquence? Pourquoi ne puis-je pas correspondre à 2 ou plusieurs lignes à l'aide de \n?

Le \n n'égaleront jamais le saut de ligne en fin de ligne, car la
retour à la ligne est toujours dépouillé avant la ligne est placée dans le
modèle de l'espace. Pour obtenir 2 ou plus de lignes dans le modèle de l'espace, de l'utilisation
le 'N' de la commande ou quelque chose de similaire (tels que les " H;...;g;').

Sed fonctionne comme ceci: sed lit une ligne à la fois, des côtelettes de porc au large de la
terminaison de ligne, met ce qui est à gauche dans le schéma de l'espace où
le script sed peut traiter ou de le modifier, et lorsque le motif de l'espace
est imprimé, ajoute un saut de ligne sur la sortie standard (ou un fichier). Si l'
modèle de l'espace est entièrement ou partiellement supprimée avec " d " ou "D", le
de retour à la ligne n'est pas ajouté dans de tels cas. Ainsi, des scripts comme

  sed 's/\n//' file       # to delete newlines from each line             
  sed 's/\n/foo\n/' file  # to add a word to the end of each line         

ne fonctionnera JAMAIS, étant donné que l'arrière de retour à la ligne est supprimée avant
la ligne est mis dans le motif de l'espace. Pour effectuer les tâches ci-dessus,
utiliser l'un de ces scripts à la place:

  tr -d '\n' < file              # use tr to delete newlines              
  sed ':a;N;$!ba;s/\n//g' file   # GNU sed to delete newlines             
  sed 's/$/ foo/' file           # add "foo" to end of each line          

Depuis les versions de sed autres que GNU sed ont des limites sur la taille de
le tampon de motif, Unix 'tr' utilitaire est préférée ici.
Si la dernière ligne du fichier contient un saut de ligne, GNU sed va ajouter
que le saut de ligne à la sortie, mais de supprimer tous les autres, alors que le tr va
supprimer tous les retours à la ligne.

Pour correspondre à un bloc de deux ou plusieurs lignes, il y a 3 choix de base:
(1) utiliser le 'N' de la commande pour ajouter la ligne Suivante à la structure de l'espace;
(2) l'utilisation de la 'H' de la commande au moins deux fois pour ajouter la ligne courante
pour le contenir d'espace, puis de récupérer les lignes de l'emprise de l'espace
avec x, g, ou G; ou (3) de l'utilisation des plages d'adresses (voir la section 3.3 ci-dessus)
pour faire correspondre les lignes entre les deux adresses spécifiées.

Choix de (1) et (2) mettre un \n dans le modèle de l'espace, où il
peut être abordée comme souhaité ('s/ABC\nXYZ/alphabet/g'). Un exemple
de l'utilisation de 'N' pour supprimer un bloc de lignes qui s'affiche dans la section 4.13
("Comment puis-je supprimer un bloc de spécifique lignes consécutives?"). Cette
exemple peut être modifié en changeant la commande supprimer pour quelque chose
d'autre, comme 'p' (impression), 'i' (insert), " c "(changement), " un " (append),
ou 's' (suppléant).

Choix (3) ne seront pas mis un \n dans le modèle de l'espace, mais il ne
correspondre à un bloc de lignes consécutives, donc peut-être que vous n'avez pas
même besoin de l' \n pour trouver ce que vous cherchez. Depuis GNU sed
version 3.02.80 prend désormais en charge cette syntaxe:

  sed '/start/,+4d'  # to delete "start" plus the next 4 lines,           

en plus de la traditionnelle '/à partir d'ici/,/y/{...}' gamme
les adresses, il peut être possible d'éviter l'utilisation de \n entièrement.

219voto

Thor Points 13562

Une courte awk alternative:

awk 1 ORS=' '

Explication

Un programme awk est constitué de règles qui sont composées de code conditionnel-blocs. Si le bloc de code est omis, la valeur par défaut ({ print $0 }) est utilisé. Ainsi, l' 1 est interprétée comme un vrai état et print $0 est exécuté pour chaque ligne.

Lors de l' awk lit l'entrée, il se divise en enregistrements basés sur la valeur de RS (Séparateur d'Enregistrement), qui, par défaut, est un retour à la ligne, ainsi awk , par défaut, analyse l'entrée linewise. La séparation implique aussi de dépouiller RS à partir de l'enregistrement d'entrée.

Maintenant, lors de l'impression d'un enregistrement, ORS (Sortie le Séparateur d'Enregistrement) est ajouté à la fin (la valeur par défaut est de nouveau un retour à la ligne). Donc, en changeant ORS de un espace de tous les retours à la ligne sont modifiées pour des espaces.

84voto

ire_and_curses Points 32802

La version en perl fonctionne comme attendu.

perl -i -p -e 's/\n//' file

Edit: Comme l'a souligné dans les commentaires, il est intéressant de noter que ceci modifie en place. -i.bak va vous donner une copie de sauvegarde du fichier d'origine avant le remplacement, dans le cas où votre regex n'est pas aussi intelligent que vous le pensiez.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X