The answers/comments so far stating that $
matches the end of line are misleading. $
in a regexp matches end of string, that is all. The reason it appears to match end of line in sed is that by default sed reads 1 line at a time so in that context (but not in others) each string it's operating on does end at the end of the line.
So $
matches end-of-string and if your string ends at the end of a line then $
matches at the end of the line but if your string contains multiple lines (e.g. in sed you can create a multi-line string stored in a buffer) then $
does not match at the end of any given line, it simply and consistently matches at the end of the string.
Similarly ^
matches start-of-string, btw, not start-of-line as you may hear people claim.
wrt your comment:
my original line is hello, world \n$ and $ is invisible , and $ is replaced by \r, now my line is hello, world\n\r$ .`
No, that is not what is happening. Your original line is:
hello, world\n
and sed reads one \n
-separated line at a time so what is read into seds buffer is the string:
hello, world
Now $
is a regexp metacharacter that matches the end-of-string so given the above string $
will match after the d
(and ^
would match before h
) so when you do
s/$/\r/
It changes the above string to:
hello world\r
and then when sed prints it out it adds back the newline (because a string with no terminating newline is not a text line per POSIX) and to outputs:
hello world\r\n
Note that $
is never part of the string, it's just a metacharacter that when used in a regexp matches the end of the string so you can test for characters appearing just at the end of a string or do other operations (like the above) after the end of the string.