Comment puis-je convertir par programmation (c'est-à-dire sans utiliser vi
) les nouvelles lignes DOS/Windows en Unix?
Les commandes dos2unix
et unix2dos
ne sont pas disponibles sur certains systèmes. Comment puis-je les émuler avec des commandes telles que sed
/awk
/tr
?
Vous pouvez utiliser tr
pour convertir de DOS en Unix; Toutefois, vous ne pouvez le faire en toute sécurité que si CR apparaît dans votre fichier uniquement en tant que premier octet d'une paire d'octets CRLF. C'est généralement le cas. Vous utilisez alors:
tr -d '\015' <DOS-file >UNIX-file
Notez que le nom DOS-file
est différent du nom UNIX-file
; si vous essayez d'utiliser le même nom deux fois, vous vous retrouverez sans données dans le fichier.
Vous ne pouvez pas le faire dans l’inverse (avec le "tr" standard).
Si vous savez entrer un retour chariot dans un script (control-V, control-M entrer dans control-M), puis:
sed 's/^M$//' # DOS to Unix
sed 's/$/^M/' # Unix to DOS
où "^ M" est le caractère de contrôle-M. Vous pouvez également utiliser le mécanisme bash
citation ANSI-C pour spécifier le retour à la ligne:
sed $'s/\r$//' # DOS to Unix
sed $'s/$/\r/' # Unix to DOS
Cependant, si vous devez le faire très souvent (plus d'une fois, en gros), il est beaucoup plus judicieux d'installer les programmes de conversion (par exemple, dos2unix
et unix2dos
, ou peut-être dtou
et utod
) et les utiliser.
tr -d "\r" < file
jetez un coup d'oeil ici pour des exemples utilisant sed
:
# IN UNIX ENVIRONMENT: convert DOS newlines (CR/LF) to Unix format.
sed 's/.$//' # assumes that all lines end with CR/LF
sed 's/^M$//' # in bash/tcsh, press Ctrl-V then Ctrl-M
sed 's/\x0D$//' # works on ssed, gsed 3.02.80 or higher
# IN UNIX ENVIRONMENT: convert Unix newlines (LF) to DOS format.
sed "s/$/`echo -e \\\r`/" # command line under ksh
sed 's/$'"/`echo \\\r`/" # command line under bash
sed "s/$/`echo \\\r`/" # command line under zsh
sed 's/$/\r/' # gsed 3.02.80 or higher
Utilisez sed -i
pour la conversion sur place, par exemple. sed -i 's/..../' file
.
Faire cela avec POSIX est délicat:
POSIX Sed ne prend pas en charge \r
ni \15
. Même si c'était le cas, l'option en place -i
n'est pas POSIX.
POSIX Awk prend en charge \r
et \15
, mais l'option -i inplace
is n'est pas POSIX
d2u et dos2unix ne sont pas utilitaires POSIX , mais ex est
POSIX ex ne prend pas en charge \r
, \15
, \n
ou \12
Pour supprimer les retours chariot:
ex -bsc '%!awk "{sub(/\r/,\"\")}1"' -cx file
Pour ajouter des retours chariot:
ex -bsc '%!awk "{sub(/$/,\"\r\")}1"' -cx file
En utilisant AWK, vous pouvez faire:
awk '{ sub("\r$", ""); print }' dos.txt > unix.txt
En utilisant Perl, vous pouvez faire:
Perl -pe 's/\r$//' < dos.txt > unix.txt
Ce problème peut être résolu avec des outils standard, mais il y a suffisamment de pièges pour les imprudents que je vous recommande d'installer la commande flip
, écrite il y a plus de 20 ans par Rahul Dhesi, l'auteur de Zoo
. Il fait un excellent travail de conversion des formats de fichiers tout en évitant, par exemple, la destruction par inadvertance de fichiers binaires, ce qui est un peu trop facile si vous vous contentez de modifier tous les CRLF que vous voyez ...
Les solutions publiées jusqu’à présent ne traitent qu’une partie du problème, à savoir la conversion du CRLF de DOS/Windows en LF d’Unix; la partie qui leur manque est que DOS utilise CRLF en tant que ligne séparateur , tandis qu'Unix utilise LF en tant que ligne terminateur . La différence est qu'un fichier DOS (généralement) n'aura rien après la dernière ligne du fichier, contrairement à Unix. Pour effectuer la conversion correctement, vous devez ajouter le LF final (sauf si le fichier a une longueur égale à zéro, c’est-à-dire qu’il ne contient aucune ligne du tout). Mon incantation préférée pour cela (avec un peu de logique supplémentaire pour manipuler des fichiers séparés par un CR de style Mac, et non pour molester des fichiers qui sont déjà au format unix) est un peu Perl:
Perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt
Notez que cela envoie la version Unixified du fichier à stdout. Si vous souhaitez remplacer le fichier par une version Unixified, ajoutez l'indicateur -i
de Perl.
Si vous n'avez pas accès à dos2unix, mais pouvez lire cette page, vous pouvez copier/coller dos2unix.py à partir d'ici.
#!/usr/bin/env python
"""\
convert dos linefeeds (crlf) to unix (lf)
usage: dos2unix.py <input> <output>
"""
import sys
if len(sys.argv[1:]) != 2:
sys.exit(__doc__)
content = ''
outsize = 0
with open(sys.argv[1], 'rb') as infile:
content = infile.read()
with open(sys.argv[2], 'wb') as output:
for line in content.splitlines():
outsize += len(line) + 1
output.write(line + '\n')
print("Done. Saved %s bytes." % (len(content)-outsize))
Cross-posted from superuser .
Super duper facile avec PCRE;
En tant que script, ou remplacez $@
par vos fichiers.
#!/usr/bin/env bash
Perl -pi -e 's/\r\n/\n/g' -- $@
Cela écrasera vos fichiers en place!
Je recommande de ne faire cela qu'avec une sauvegarde (contrôle de version ou autre)
Une solution awk encore plus simple sans programme:
awk -v ORS='\r\n' '1' unix.txt > dos.txt
Techniquement '1' est votre programme, b/c awk en nécessite un lorsque l'option vous est donnée.
UPDATE: Après avoir consulté cette page pour la première fois depuis longtemps, je me suis rendu compte que personne n’avait encore posté de solution interne, en voici une:
while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt
Vous pouvez utiliser vim par programme avec l'option -c {commande}:
Dos à Unix:
vim file.txt -c "set ff=unix" -c ":wq"
Unix à dos:
vim file.txt -c "set ff=dos" -c ":wq"
"set ff = unix/dos" signifie changer le format de fichier (ff) du fichier au format de fin de ligne Unix/DOS
": wq" signifie écrire un fichier sur le disque et quitter l'éditeur (permettant d'utiliser la commande dans une boucle)
Pour convertir un fichier en place, faites
dos2unix <filename>
Pour convertir le texte converti dans un autre fichier, faites
dos2unix -n <input-file> <output-file>
Il est déjà installé sur Ubuntu et est disponible sur homebrew avec brew install dos2unix
Je sais que la question demande explicitement d’autres solutions que cet utilitaire, mais c’est le premier résultat de recherche de Google pour "convertir les fins de ligne Unix".
fait intéressant dans mon git-bash sur Windows sed ""
a déjà fait le tour:
$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text
Je suppose que sed les ignore lors de la lecture des lignes depuis l'entrée et écrit toujours les fins de ligne Unix en sortie.
Cela a fonctionné pour moi
tr "\r" "\n" < sampledata.csv > sampledata2.csv
TIMTOWTDI!
Perl -pe 's/\r\n/\n/; s/([^\n])\z/$1\n/ if eof' PCfile.txt
Basé sur @GordonDavisson
Il faut envisager la possibilité de [noeol]
...
Il fallait juste réfléchir à la même question (côté Windows, mais également applicable à Linux.) Étonnamment, personne n’a mentionné une méthode très automatisée de conversion CRLF <-> LF pour les fichiers texte utilisant la bonne vieille option Zip -ll
(Info -Zip *: français):
Zip -ll textfiles-lf.Zip files-with-crlf-eol.*
unzip textfiles-lf.Zip
REMARQUE: cela créerait un fichier Zip en conservant les noms de fichier d'origine, mais en convertissant les fins de ligne en LF. Ensuite, unzip
extrairait les fichiers selon le format compressé, c'est-à-dire avec leurs noms d'origine (mais avec des fins LF), invitant ainsi à remplacer les fichiers d'origine locaux, le cas échéant.
Extrait pertinent du Zip --help
:
Zip --help
...
-l convert LF to CR LF (-ll CR LF to LF)
Vous pouvez utiliser awk. Définissez le séparateur d'enregistrement (RS
) sur une expression rationnelle qui correspond à tous les caractères de nouvelle ligne possibles. Et définissez le séparateur d'enregistrement de sortie (ORS
) sur le caractère de nouvelle ligne de style unix.
awk 'BEGIN{RS="\r|\n|\r\n|\n\r";ORS="\n"}{print}' windows_or_macos.txt > unix.txt
Pour Mac OSX si vous avez installé homebrew [ http://brew.sh/][1]
brew install dos2unix
for csv in *.csv; do dos2unix -c mac ${csv}; done;
Vérifiez que vous avez bien copié les fichiers, car cette commande modifiera les fichiers en place . L'option -c mac rend le commutateur compatible avec osx.
Sous Linux, il est facile de convertir ^ M (ctrl-M) en * nix newlines (^ J) avec sed.
Ce sera quelque chose comme ceci sur la CLI, il y aura en fait un saut de ligne dans le texte. Cependant, le\passe que ^ J le long de sed:
sed 's/^M/\
/g' < ffmpeg.log > new.log
Vous obtenez cela en utilisant ^ V (ctrl-V), ^ M (ctrl-M) et\(barre oblique inverse) lorsque vous tapez:
sed 's/^V^M/\^V^J/g' < ffmpeg.log > new.log
En tant qu'extension de la solution Unix vers DOS de Jonathan Leffler, pour convertir en toute sécurité en DOS lorsque vous n'êtes pas sûr des fins de ligne du fichier
sed '/^M$/! s/$/^M/'
Ceci vérifie que la ligne ne se termine pas déjà par CRLF avant d'être convertie en CRLF.
J'ai créé un script en fonction de la réponse acceptée afin que vous puissiez le convertir directement sans avoir besoin d'un fichier supplémentaire, puis supprimer et renommer.
convert-crlf-to-lf() {
file="$1"
tr -d '\015' <"$file" >"$file"2
rm -rf "$file"
mv "$file"2 "$file"
}
assurez-vous simplement que si vous avez un fichier comme "fichier1.txt" que "fichier1.txt2" n'existe pas déjà ou qu'il sera écrasé, je l'utilise comme emplacement temporaire pour stocker le fichier.
sed --expression='s/\r\n/\n/g'
Étant donné que la question mentionne sed, il s'agit du moyen le plus simple d'utiliser sed pour atteindre cet objectif. Ce que l'expression dit, c'est remplacer tout retour chariot et saut de ligne par un saut de ligne uniquement. C'est ce dont vous avez besoin lorsque vous passez de Windows à Unix. J'ai vérifié que ça marche.