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?
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.)
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
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
Une autre méthode
awk 1 RS='\r\n' ORS=
\r\n
1
est toujours vrai, et en l'absence d'un bloc d'action {print}
est utilisé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