web-dev-qa-db-fra.com

Suppression des sauts de ligne Windows sous Linux (sed vs awk)

Avoir des fichiers délimités avec des caractères de nouvelle ligne mal placés au milieu des champs (pas des fins de ligne), apparaissant comme ^ M dans Vim. Ils proviennent des exportations freebcp (sur Centos 6) d'une base de données MSSQL. Le vidage des données en hexadécimal montre des modèles\r\n:

$ xxd test.txt | grep 0d0a
0000190: 3932 3139 322d 3239 3836 0d0a 0d0a 7c43

Je peux les supprimer avec awk, mais je ne peux pas faire de même avec sed.

Cela fonctionne en awk, supprimant complètement les sauts de ligne:

awk 'gsub(/\r/,""){printf $0;next}{print}'

Mais ce n'est pas le cas dans sed, laissant les sauts de ligne en place:

sed -i 's/\r//g'

où cela semble n'avoir aucun effet:

sed -i 's/\r\n//g'

L'utilisation de ^ M dans l'expression sed (ctrl + v, ctrl + m) ne semble pas non plus fonctionner.

Pour ce genre de tâche, sed est plus facile à gérer, mais je travaille à en apprendre davantage sur les deux. Suis-je mal utilisé sed, ou y a-t-il une limitation?

29
kermatt

Je pense que certaines versions de sed ne reconnaîtront pas \r en tant que personnage. Cependant, vous pouvez utiliser une fonction bash pour contourner cette limitation:

echo $string | sed $'s/\r//'

Ici, vous laissez bash remplacer '\ r' par le caractère de retour chariot réel à l'intérieur du $'...' construire avant de passer cela à sed comme commande. (En supposant que vous utilisez bash; les autres shells devraient avoir une construction similaire.)

20
chepner

Vous pouvez utiliser l'outil de ligne de commande dos2unix

dos2unix input

Ou utilisez la commande tr:

tr -d '\r' <input >output

En fait, vous pouvez faire le changement de format de fichier dans vim:

:e ++ff=dos
:w ++ff=unix
:e!
:e ++ff=dos
:set ff=unix
:w

MODIFIER

Si vous souhaitez supprimer le \r\n séquences dans le fichier, essayez ces commandes dans vim:

:e ++ff=unix           " <-- make sure open with UNIX format
:%s/\r\n//g            " <-- remove all \r\n
:w                     " <-- save file

Votre solution awk fonctionne bien. Deux autres solutions sed:

sed '1h;1!H;$!d;${g;s/\r\n//g}' input
sed ':A;/\r$/{N;bA};s/\r\n//g' input
39
kev

Une autre méthode

awk 1 RS='\r\n' ORS=
  • définissez Record Separator sur \r\n
  • définissez le séparateur d'enregistrement de sortie sur une chaîne vide
  • 1 est toujours vrai, et en l'absence d'un bloc d'action {print} est utilisé
6
Steven Penny

sed -e 's/\r//g' input_file

Cela fonctionne pour moi. La différence de - e au lieu de - i commande.

J'ai également mentionné que voir sur différentes plates-formes se comportait différemment. Le mien est:sed --version This is not GNU sed version 4.0

4
Sergiy Dolnyy