2

I was working on the conversion of Unix newline to Windows newline. I tried to unix2dos but it gave me some binary error, so I looked it up and stumbled upon this regex

sed 's/$'"/`echo \\\r`/" input.txt > output.txt

This regex is working but I have got no clue, how is it working? Obviously I am trying to interpret it through this form

sed 's/a/b/'

Here

a refers $'" which I don't understand.
and b refers echo \\\r which means '\r'

Also I don't understand why/how combination of single and double quote is being used? Can anyone explain this regular expression to me?

2 Answers 2

5

There is no $'"

's/$'"/`echo \\\r`/" == "s/\$/`echo \\\r`/"

But the regex author just liked to escape $ via single quote.

You can combine such escaping in any way you like.

So your regex it just appends \r to the end of the line.

update. Initially it wasn't clear from question that it uses `echo \\\r` instead of just echo \\\r. There is no need to use echo here. You can just do it directly in sed:

sed 's/$/\r/'
4
  • Ok, Can't I use '\r' directly instead of using it with echo.
    – Max
    Nov 15, 2013 at 19:39
  • @JoeDimaggio You can use it directly. Initially ` symbol was hidden in your question. I updated my answer.
    – rush
    Nov 15, 2013 at 19:44
  • Wow from that regex to this regex! :D. One more question though, It seems like the line-break in windows in \r\nEOL. But I feel like this regex will give /n\rEOL. so what am I missing here?
    – Max
    Nov 15, 2013 at 19:49
  • @JoeDimaggio actually in sed \n is outside working pattern ( except cases when several lines are in the buffer, but even in that case the last \n will be outside the buffer ) and \r will appear just before \n.
    – rush
    Nov 15, 2013 at 21:14
1

That's some complex quoting. The argument to sed is built up from two parts. First, there's 's/$', a single-quoted string literal, yielding the characters s/$. Then there's a double-quoted string, which contains the command substitution `echo \\\r`. This runs the command echo \r, which depending on the shell either prints \r or a CR character. (The text printed by echo ends in a newline, but the command substitution eats it up.) In order for this command to have the desired effect, you must be on a system where echo \r prints a CR character, which I'll represent here as .

The argument to sed is thus s/$/␍/. This replaces every match of the regular expression $ by the string . The regex $ matches the empty string, but only at the end of a line, so this sed command appends a CR to every line. Since a Unix line ends with LF while a Windows line ends with CR+LF, this transforms Unix line endings into Windows line endings.

GNU sed, but not other versions, understand backslash escapes such as \r. So with GNU sed you can write sed 's/$/\r/'. However, this doesn't work with other sed implementations (BSD, Solaris, …). echo \r isn't very portable either. A portable solution is to use tr, which has backslash escapes as a standard.

sed "$(echo 's/$/@/' | tr '@' '\r')"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .