ChatGPT解决这个技术问题 Extra ChatGPT

Preserve line endings

I run sed to do some substitution on windows and I noticed that it automatically converts line endings to Unix (\n). Is there an option to tell sed to use Windows line endings (\r\n) or even better to preserve the line endings from the file?

Note: I use sed from unxutils: http://unxutils.sourceforge.net/

The solutions below do not work on macOS.
I even got this far and it still didn't work LC_ALL=C perl -i -e 'binmode $STDIN;undef $/;$_=<>;s|http://911coned.com|https://911coned.com|gm;print' education.html
So actually the command above does work and I just discovered a bug in the git diff program.
You can use sed (without any special options) + unix2dos

J
Joseph Thomson

You can use the -b option for sed to have it treat the file as binary. This will fix the problem with cygwin's sed on Windows.

Example: sed -b 's/foo/bar/'

If you wish to match the end of the line, remember to match, capture and copy the optional carriage return.

Example: sed -b 's/foo\(\r\?\)$/bar\1/'

From the sed man page:

-b --binary This option is available on every platform, but is only effective where the operating system makes a distinction between text files and binary files. When such a distinction is made—as is the case for MS-DOS, Windows, Cygwin—text files are composed of lines separated by a carriage return and a line feed character, and sed does not see the ending CR. When this option is specified, sed will open input files in binary mode, thus not requesting this special processing and considering lines to end at a line feed.`


Note that this does not work with sed -i on cygwin (for me), but you can work around that. Thanks for the update -- the other answers were the last word on this subject for a while.
Note, this option is not available with sed on Mac.
Works for me even with sed -i: it is just important how to type it. While sed -bi and sed -i -b work, sed -ib does not work: see the man page for why (uses the b as the suffix for the backup copy).
Use: sed -bi 's/foo/bar/'
Does not work for me in Windows cygwin. On the lines that sed made the change, the line endings is Unixy. The rest of lines have Windowish line-endings. Thus my file got a mixed of lines with different line endings.
S
SiegeX

You could try to sub the \n for \r\n at the end of your existing script like so:

sed 's/foo/bar/;s/$/\r/'

or perhaps

 sed -e 's/foo/bar/' -e 's/$/\r/'

If neither of the above two work, you'll have to consult the specific man page for your version of sed to see if such an option exists. Note that the *nix versions of sed do not alter the line terminators without being told to do so.

Another alternative is to use the cygwin version of sed which shouldn't have this undesirable behavior.


The cygwin version does have this undesirable behavior.
If file contains both \n (0x0A) and \r\n (0x0D 0x0A) - this proposed solution (of always re-injecting the \r) breaks it.
This works for me using MSYS2/MinGW. Thank you @SiegeX.
s
seeker

Alternatively, (the cygwin version of) perl -pe doesn't seem to have this problem.


sed on MacOS does not have the -b option and has similar issues as described in the original question. The perl alternative doesn't have this issue, so thanks for your suggestion. sed -i -e 's/<img[^>]*\/>//g' *.xml replaces line endings by '\n' perl -i -p -e 's/<img[^>]*\/>//g' *.xml preserves the original line endings
b
buckley

Gnuwin can be suppressed to mess up the newlines (win->unix) if you only specify the -b switch and redirect. Using the -i (inline) switch will mess it up.

E.g. sed.exe -b "s/\xFF\xFE//" c:\temp\in.csv > c:\temp\out.csv


See a version with working -i mode in my answer.
V
Vadzim

I've found that sed-4.4.exe from https://github.com/mbuilov/sed-windows is pure win as it

uses windows CRLF line endings in default mode

preserves original line endings in -b mode

works correctly with in-place -i mode

also offers -z mode with \0 delimeters instead of \n which may be handy sometimes too

See also list of sed options and list of all windows sed ports.

Note that gnuwin32 sed 4.2.1 does corrupt line endings in -bi mode and doesn't have -z mode at all.