1
echo "hi,my,name,is" | sed 's/,/\n/g' >out.txt

yields:

hi
my
name
is

But in reverse:

sed 's/\n/,/g' out.txt

yields:

hi
my
name
is

Why doesn't sed revert the operation with an inversion of the replace operation?

don_crissti
  • 79,330
  • 30
  • 216
  • 245
alexei.net
  • 11
  • 2
  • because sed/awk strips the record separator (newline in your case) and adds back while printing... perl/ruby wont.. so you'd get your inversion there.. – Sundeep Mar 09 '18 at 05:42

2 Answers2

5

Try:

$ sed 'H;1h;$!d;x; s/\n/,/g' out.txt
hi,my,name,is

By default, sed reads in only one line at a time, processes it, and prints it. Since a single line never has a newline character, the command s/\n/,/g does nothing. The solution, as above, is to read the whole file in at once and then do s/\n/,/g.

The commands H;1h;$!d;x read the whole file in at once. It is probably simplest to think of this as an idiom. If you really want to know the gory details:

  • H - Append current line to hold space
  • 1h - If this is the first line, overwrite the hold space with it
  • $!d - If this is not the last line, delete pattern space and jump to the next line.
  • x - Exchange hold and pattern space to put whole file in pattern space

Alternative: awk

$ awk 'NR>1{printf ","} {printf "%s",$0} END{print""}' out.txt
hi,my,name,is

Or:

$ awk '{printf "%s%s",(NR==1?"":","),$0} END{print""}' out.txt
hi,my,name,is
John1024
  • 73,527
  • 11
  • 167
  • 163
  • 1
    Or just `tr '\n' ,` – Sparhawk Mar 09 '18 at 04:01
  • @Sparhawk Very true. But, as you saw in the title of this question, the OP knew about the `tr` approach. He was looking for a better understanding of `sed`. – John1024 Mar 09 '18 at 04:18
  • Arrgghh, yes, true. I missed that, sorry. (+1) – Sparhawk Mar 09 '18 at 04:24
  • Three more awk ways: `{printf "%s",t $0; t=","} END{print""}` or `{t=t "," $0} END{print substr(t,2)}` optionally with redundant `BEGIN{t=""}` or `-vt=` for clarity; or on condition none of the lines are empty `-vRS="" '{gsub(/\n/,","); print}'` (which is almost like the sed) – dave_thompson_085 Mar 09 '18 at 06:03
2

With gnu sed

echo "hi,my,name,is" | sed 's/,/\n/g' | sed -z 's/\n/,/g'
ctac_
  • 1,960
  • 1
  • 6
  • 14